最近用shiro 做后台权限,发现shiro无法解决跨域OPTIONS类型的请求,网上很多人用 shiroFilterFactoryBean.getFilters().put("authc",new CustomFilter()); 这种方式,发现可以解决OPTIONS问题,但是无法解决session验证问题。
经过各种尝试,最终发现这篇文章的方式解决了我的问题。
https://urzz.xyz/2019/06/05/spring-shiro-cors-config/
通过 CorsFilter 的方式
@Bean
public FilterRegistrationBean corsFilter() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
final CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.setMaxAge(15000L);
config.addAllowedMethod("OPTIONS");
config.addAllowedMethod("HEAD");
config.addAllowedMethod("GET");
config.addAllowedMethod("PUT");
config.addAllowedMethod("POST");
config.addAllowedMethod("DELETE");
config.addAllowedMethod("PATCH");
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
// 设置监听器的优先级
bean.setOrder(-1);
return bean;
}
CorsFilter 继承自 OncePerRequestFilter,通过跟踪CorsFilter 源码发现doFilterInternal 方法中 调用了 CorsUtils.isPreFlightRequest(request)方法,该方法对请求方式为OPTIONS的请求进行了过滤
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
if (CorsUtils.isCorsRequest(request)) {
CorsConfiguration corsConfiguration = this.configSource.getCorsConfiguration(request);
if (corsConfiguration != null) {
boolean isValid = this.processor.processRequest(corsConfiguration, request, response);
if (!isValid || CorsUtils.isPreFlightRequest(request)) {
return;
}
}
}
filterChain.doFilter(request, response);
}
public static boolean isPreFlightRequest(HttpServletRequest request) {
return (isCorsRequest(request) && HttpMethod.OPTIONS.matches(request.getMethod()) &&
request.getHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD) != null);
}
确保 corsFilter 的拦截在 shiro 的拦截器之前执行就可以。
网友评论