Spring-security 的 CORS 问题

Posted

技术标签:

【中文标题】Spring-security 的 CORS 问题【英文标题】:CORS problems with Spring-security 【发布时间】:2016-10-30 15:21:45 【问题描述】:

我正在使用 Spring-boot(http://localhost:8080)和 angular(http://localhost:80)构建一个应用程序。

前端和后端代码由 2 个不同的服务器提供服务。为了避免 CORS 问题,我曾经放置了一个中间 nginx 服务器,但我对这个解决方案不再满意。因此,我必须允许 CORS。

我通过这些行在全球范围内允许 CORS:

@Configuration
public class WebMvcConfiguration extends WebMvcConfigurerAdapter    

  @Override
  public void addCorsMappings(CorsRegistry registry) 
    registry.addMapping("/**")
        .allowedOrigins("http://localhost")
        .allowCredentials(true)
    ;
  

适用于每个路由除了身份验证路由,它由 Spring 安全性处理:

public class SecurityConfiguration extends WebSecurityConfigurerAdapter 

  @Override
  public void configure(HttpSecurity http) throws Exception 
    http
      .formLogin()
      .successHandler(successHandler())
      .failureHandler(failureHandler())
    //[...]
  

  private AuthenticationSuccessHandler successHandler() 
    return (httpServletRequest, httpServletResponse, authentication) ->
      httpServletResponse.setStatus(HttpServletResponse.SC_OK);
  

  private AuthenticationFailureHandler failureHandler() 
    return (httpServletRequest, httpServletResponse, e) -> 
       httpServletResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
    ;

这是在前端部分发送请求的代码:

$http.post('http://localhost:8080/api/login', $.param('username': username, 'password': password),
            headers: 'content-type': 'application/x-www-form-urlencoded'
).then(function() )
.catch(function(error) ;

如果我输入正确的密码,http 响应代码(我可以在 Chrome 控制台中看到)是 200,但我仍然到达 catch 块(error.status = -1)并且我可以看到控制台中的此错误消息:

XMLHttpRequest 无法加载 http://localhost:8080/api/login。请求的资源上不存在“Access-Control-Allow-Origin”标头。 Origin 'http://localhost' 因此不允许访问。

如果我输入了错误的密码,我也会通过以下错误消息到达 catch 块:

XMLHttpRequest 无法加载 http://localhost:8080/api/login。请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,Origin 'http://localhost' 不允许访问。响应的 HTTP 状态代码为 401。

我还注意到,当我调用身份验证端点时,CORS 响应标头丢失了。

有什么想法吗?

编辑:如果我在自定义成功处理程序中手动添加标题,它会起作用。如果 Spring-security 可以考虑全局 CORS 配置,我更愿意。

【问题讨论】:

***.com/questions/35035055/spring-boot-and-cors/… 也许这可以节省您的时间:) 【参考方案1】:

有完全相同的问题,你可以做两件事,

    @CrossOrigin(origins = "http://localhost:8080") 将此添加到服务方法中。这背后的想法是您通过服务本身启用 CORS 请求。 使用JSONP,但是有一定的限制。我也没有成功实现它,所以我使用了上面的选项。

【讨论】:

【参考方案2】:

你应该看看 Spring 网站。有消费网络服务和管理 CORS 的解决方案:

为 RESTful Web 服务启用跨源请求: https://spring.io/guides/gs/rest-service-cors/ 使用 AngularJS 使用 RESTful Web 服务: https://spring.io/guides/gs/consuming-rest-angularjs/

【讨论】:

【参考方案3】:

根据我的经验,您需要在 CORS 中包含端口号,来自浏览器的错误消息有点误导。

您可以通过检查网络并检查请求标头的 Origin 字段来验证这一点。响应标头的Access-Control-Allow-Origin 中的值必须完全匹配,包括协议和端口。

【讨论】:

以上是关于Spring-security 的 CORS 问题的主要内容,如果未能解决你的问题,请参考以下文章

Spring-Security OAuth WebMVC 无效的 CORS 请求

如何为 Webflux、Spring-Security、okta-spring-boot-starter 和 Okta-React 正确使用 CORS?

将标头添加到 oauth/token 响应(spring-security)

Spring Security CORS 不工作

在 spring 安全标签中启用 CORS

spring CORS 和 Angular 不起作用:HTTP 状态代码 403 错误