【发布时间】:2020-07-02 08:05:08
【问题描述】:
在修改了不同的安全框架之后,我决定在我的 Spring Boot RestAPI 中使用 Apache Shiro,因为它似乎提供了必要的灵活性而没有太多的官僚开销。到目前为止,除了将 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 政策,没有将“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 bean:
shiroEventBusAwareBeanPostProcessor
shiroFilterChainDefinition
shiroFilterFactoryBean
因此,我认为可能是 shiroFilterFactoryBean 以某种方式破坏了它,需要额外注意和配置。不幸的是,Apache Shiro 文档似乎没有说明跨域请求,我认为这不是(必然)Shiro 安全问题的一部分,而是底层的 Restful API,即 Spring。谷歌搜索这个问题也没有产生任何有用的结果,所以我怀疑我错过了一些大的东西,或者更糟糕的是,这里有一些小而明显的东西。虽然我正在尝试解决这个问题,但非常感谢任何帮助或提示,谢谢!
【问题讨论】:
标签: spring-boot spring-mvc cors shiro