Tomcat 8 和 Spring Security Cors
Posted
技术标签:
【中文标题】Tomcat 8 和 Spring Security Cors【英文标题】:Tomcat 8 and Spring Security Cors 【发布时间】:2020-02-26 17:18:16 【问题描述】:我正在尝试配置 Spring Security 以使其支持 CORS。 感谢这篇文章 Spring security CORS Filter,我已经使用 Spring Boot 使用此配置代码在我的本地主机上工作了:
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter
@Override
protected void configure(HttpSecurity http) throws Exception
http.cors()
.and()
.antMatcher("/api/**")
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers(HttpMethod.POST, "/api/login").permitAll()
.antMatchers(HttpMethod.GET, "/api/websocket/**").permitAll()
.antMatchers("/api/**").authenticated()
.and()
.addFilterBefore(new JWTLoginFilter("/api/login", HttpMethod.POST, authenticationManager(), tokenAuthenticationService, myUserService), UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(new JWTAuthenticationFilter(tokenAuthenticationService), UsernamePasswordAuthenticationFilter.class)
.csrf().disable();
@Bean
public CorsConfigurationSource corsConfigurationSource()
final CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(ImmutableList.of("*"));
configuration.setAllowedMethods(ImmutableList.of("HEAD",
"GET", "POST", "PUT", "DELETE", "PATCH"));
// setAllowCredentials(true) is important, otherwise:
// The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.
configuration.setAllowCredentials(true);
// setAllowedHeaders is important! Without it, OPTIONS preflight request
// will fail with 403 Invalid CORS request
configuration.setAllowedHeaders(ImmutableList.of("Authorization", "Cache-Control", "Content-Type"));
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
但是当我在远程 Tomcat 服务器上部署我的应用程序时,它不起作用:
Access to XMLHttpRequest at 'http://xxx:9080/yyy/api/user/findByLogin/?login=zzz' from origin 'http://xxx:10080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
这是失败的 OPTIONS 请求的屏幕截图:
我的本地主机上的工作请求:
我的配置类是否足够,或者我需要在 Tomcat 设置中进行设置吗? 谢谢
【问题讨论】:
你能检查你的 OPTIONS 请求是否给出了 CORS 错误吗?如果是这样,请将其添加到您允许的方法中,然后重试。 OPTIONS 请求返回 403。我添加了屏幕截图。 你能看看这篇文章吗? ***.com/questions/43699343/… 同理,解决方案在本地有效,在Tomcat上无效。 你的 pom.xml 和 main 类是什么样子的?请尝试提供minimal reproducible example。 【参考方案1】:响应 403 反映了授权失败。可能是您的服务器设置为请求选项请求的授权。您必须确保将选项配置为发送成功响应(2xx 状态代码)以允许浏览器发送实际请求。 2xx 响应通知浏览器服务器处理 CORS 请求。
您的请求在本地有效的原因可能是您在提出请求时获得了授权。因此,请检查您的身份验证以确保其正确。因此,飞行前请求不会发送任何授权标头,因此您不应期望在服务器端。
【讨论】:
【参考方案2】:只需配置 CorsFilter 以使用提供的 CorsConfigurationSource 添加相关的 CORS 响应标头(如 Access-Control-Allow-Origin)。阅读其文档了解更多信息。由于您已经拥有UrlBasedCorsConfigurationSource,您可以将过滤器配置如下:
@Bean
public FilterRegistrationBean corsFilter()
FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(corsConfigurationSource()));
bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
return bean;
只要在你的配置中加入上面提到的 bean,希望它可以工作。
这是我的完整配置,您只需要上面提到的一部分:
@Bean
public FilterRegistrationBean corsFilter()
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
config.addExposedHeader("Content-Disposition");
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
return bean;
【讨论】:
【参考方案3】:-
您的允许方法也应该有“OPTIONS”。
您是否拥有 Web 服务器?网络服务器是否也有 CORS?
【讨论】:
【参考方案4】:尝试在本地的corsConfigurationSource()
方法中放置一个调试点并检查它是否正在执行。如果它没有被执行,请调查原因 - 可能通过启用 Spring 的调试日志和/或重新检查 Spring 配置。
另外,尝试将 OPTIONS 添加到 setAllowedMethods
configuration.setAllowedMethods(ImmutableList.of("HEAD", "GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"));
【讨论】:
【参考方案5】:检查 tomcat 服务器是否在 $CATALINA_BASE/conf/web.xml 中配置了冲突的 CORS 过滤器
【讨论】:
【参考方案6】:Tomcat 也有自己的 cors 过滤器,如果您在 tomcat 之前使用其他服务器(如 nodejs、apache 服务器 vs )也要检查它的 cors 过滤器。
【讨论】:
【参考方案7】:Spring security 提供了一种在 http 配置器中配置 CORS 的方法,有一种更简洁的方法可以将 CORS 过滤器添加到应用程序中-
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class MyCORSFilterClass implements Filter
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me");
chain.doFilter(req, res);
@Override
public void init(FilterConfig filterConfig)
@Override
public void destroy()
以最高优先级排序过滤器确保 javax.servlet.Filter 的 MyCORSFilterClassimplementation 是链中的第一个。
【讨论】:
使用过滤器,它可以在本地工作(如果你在 WebSecurityConfigurerAdapter 中添加 http.cors()),但仍然不能在我的 Tomcat 服务器上。 对我来说同样的问题。任何解决方案@ClémentPicou?以上是关于Tomcat 8 和 Spring Security Cors的主要内容,如果未能解决你的问题,请参考以下文章
Tomcat 8 和 Spring Security Cors
Spring Boot YML 和独立 Tomcat 8 服务器
Spring Security 和 Tomcat 8 JSessionId 响应不匹配
Spring Security和Tomcat 8 JSessionId响应不匹配
Grails 3 Spring Security LDAP 插件和 Tomcat 8
在调用处理程序之前使用 Tomcat 8 和 Spring 4 ClassCastException 的 websockets