Apache Shiro正在破坏我的Spring Boot RestAPI的CORS配置

问题描述 投票:0回答:1

在修改了不同的安全框架之后,我决定将Apache Shiro用于我的Spring Boot RestAPI,因为它似乎提供了必要的灵活性而又没有太多的官僚主义开销。到目前为止,除了将maven依赖项添加到我的项目之外,我什么都没做:

<dependency>
  <groupId>org.apache.shiro</groupId>
  <artifactId>shiro-spring-boot-web-starter</artifactId>
  <version>1.5.1</version>
</dependency>

这迫使我定义一个Realm bean来启动应用程序:

@Bean
public Realm realm() {
    return new TMTRealm();
}

除了实现Realm接口之外,bean几乎什么都没做:

public class TMTRealm implements Realm {

private static final String Realm_Name = "realm_name";

@Override
public String getName() {
    return Realm_Name;
}

@Override
public boolean supports(AuthenticationToken token) {
    return false;
}

@Override
public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
    return null;
}

}

到目前为止,一切都很好。除了现在,我的RestAPI违反了CORS策略,没有在其响应的any中添加“ Access-Control-Allow-Origin”标头。我注意到,Chrome不会发送任何专用的OPTIONS请求,但会发送相同方法的两个请求,在这种情况下为GET,第一个请求失败,如下所示:

Access to XMLHttpRequest at 'http://localhost:8081/geo/country/names?typed=D&lang=en-US' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

[没有Shiro的话,它就可以很好地工作,既可以在控制器上使用Spring的@CrossOrigin注释的优雅方式,也可以通过蛮力'守旧'的方式定义CorsFilter bean:

@Bean
public CorsFilter corsFilter() {
    final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    final CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.setAllowedOrigins(Arrays.asList("*"));
    config.setAllowedHeaders(Arrays.asList("*"));
    config.setAllowedMethods(Arrays.asList("OPTIONS", "GET", "POST", "PUT", "DELETE"));
    source.registerCorsConfiguration("/**", config);
    return new CorsFilter(source);
}

我已经实现了Spring的ApplicationListener接口,以在ApplicationContext启动时挂入,因此可以看到corsFilter bean已注册并存在:

@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
    System.out.println("############ - application context started with beans: ");
    final String[] beans = event.getApplicationContext().getBeanDefinitionNames();
    Arrays.parallelSort(beans);
    for (final String bean : beans) {
        System.out.println(bean);
    }
}

输出:

...
conditionEvaluationDeltaLoggingListener
conventionErrorViewResolver
corsFilter
countryController
...

但是过滤器永远不会在任何请求下调用(我已经设置了一个断点和System.out来证明它)。我还注意到存在三种Shiro豆:

shiroEventBusAwareBeanPostProcessor
shiroFilterChainDefinition
shiroFilterFactoryBean

因此,我认为shiroFilterFactoryBean可能会以某种方式破坏它,因此需要额外的注意和配置。不幸的是,Apache Shiro文档似乎没有提及跨域请求,我认为这(不是必要)不是Shiro的安全问题的一部分,而是底层的Restful API(即Spring)。谷歌搜索该问题也未产生任何有益的结果,因此我怀疑我在这里缺少了一些大的或更糟的东西。当我尝试解决这个问题时,我们非常感谢您的帮助或提示,谢谢!

spring-boot spring-mvc cors shiro
1个回答
0
投票

好吧,我知道了。我在filter-servlet领域已经有一段时间了,所以我没有想到执行过滤器的顺序。我这样做的天真的方法是,Shiro过滤器链始终在我的自定义CorsFilter(显然还有@CrossOrigin注释的默认Spring处理器)之前执行。由于尚未配置Shiro,因此任何请求都不会被身份验证或授权,因此将被拒绝,因此,CorsFilter从未执行过,如果没有Access-Control-Allow-Origin标头,就不会引起响应。

因此,我可以正确配置Shiro或只是通过使用Spring的FilterRegistrationBean像这样(将setOrder设置为零)来确保在Shiro过滤器之前执行CorsFilter。

@Configuration
public class RestApiConfig {

@Bean
public FilterRegistrationBean<CorsFilter> corsFilterRegistrationBean() {
    final FilterRegistrationBean<CorsFilter> registration = new FilterRegistrationBean<>(this.corsFilter());
    registration.setOrder(0);
    return registration;
}

private CorsFilter corsFilter() {
    final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    final CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.setAllowedOrigins(Arrays.asList("*"));
    config.setAllowedHeaders(Arrays.asList("*"));
    config.setAllowedMethods(Arrays.asList("OPTIONS", "GET", "POST", "PUT", "DELETE"));
    source.registerCorsConfiguration("/**", config);
    return new CorsFilter(source);
}

@Bean
public Realm realm() {
    return new TMTRealm();
}

}

我确定会有一种更优雅的方法,特别是因为我想使用Spring注释,但是现在这行得通。也许会帮助某人。

© www.soinside.com 2019 - 2024. All rights reserved.