Spring Security中/oauth/token接口的CORS配置问题(3.1+4.3.12)
解决Spring Security OAuth2 /oauth/token接口的CORS问题
我明白你遇到的困扰了——Spring MVC的mvc:cors配置对/oauth/token接口完全不起作用,这是因为该接口的请求会被Spring Security的过滤器链优先拦截处理,根本没走到Spring MVC的DispatcherServlet环节,所以MVC层面的CORS配置完全没机会生效。
下面是针对Spring Security 3.1的可行解决方案:
1. 自定义CORS过滤器
创建一个CORS过滤器,让它在所有Spring Security过滤器之前执行,这样就能在响应中正确添加CORS头,处理浏览器的跨域预检请求。
import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.filter.OncePerRequestFilter; import java.io.IOException; public class CORSFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { // 允许你的前端域名跨域 response.setHeader("Access-Control-Allow-Origin", "http://localhost:4200"); // 允许的请求方法(包含OAuth2令牌接口需要的方法) response.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); // 允许的请求头,覆盖OAuth2认证所需的头信息 response.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, Accept"); // 允许携带凭证(如果你的请求需要传递Cookie等信息) response.setHeader("Access-Control-Allow-Credentials", "true"); // 处理浏览器的预检OPTIONS请求,直接返回200状态码,无需进入后续过滤器链 if ("OPTIONS".equalsIgnoreCase(request.getMethod())) { response.setStatus(HttpServletResponse.SC_OK); } else { // 非预检请求,继续执行后续的Security过滤器链 filterChain.doFilter(request, response); } } }
2. 在Spring Security配置中添加该过滤器
修改你的spring-security.xml,把自定义的CORS过滤器放在所有过滤器的最前面,确保它能最先处理请求:
<!-- 定义CORS过滤器Bean --> <bean id="corsFilter" class="com.your.package.CORSFilter" /> <!-- /oauth/token接口的Security配置 --> <http pattern="/oauth/token" create-session="stateless" authentication-manager-ref="clientAuthenticationManager" xmlns="http://www.springframework.org/schema/security"> <!-- 将CORS过滤器放在第一个执行,确保响应头被提前添加 --> <custom-filter ref="corsFilter" before="FIRST" /> <intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" /> <anonymous enabled="false" /> <http-basic entry-point-ref="clientAuthenticationEntryPoint" /> <custom-filter ref="clientCredentialsTokenEndpointFilter" after="BASIC_AUTH_FILTER" /> <access-denied-handler ref="oauthAccessDeniedHandler" /> </http>
为什么之前的配置无效?
Spring Security的过滤器链优先级远高于Spring MVC的DispatcherServlet,当请求到达/oauth/token时,Security的过滤器会先拦截并处理请求,此时MVC的CORS拦截器还没机会介入,自然无法添加CORS响应头。通过把自定义CORS过滤器放在Security过滤器之前,就能保证响应头被正确添加到所有跨域请求中。
另外,你的报错里还包含HTTP 400状态码,解决CORS问题后,建议检查请求参数是否符合OAuth2规范(比如grant_type、client_id等参数是否正确传递)。
内容的提问来源于stack exchange,提问作者Chris Hadfield
相关产品推荐
相关产品推荐

