在 Spring 服务器中使用 OAuth 身份验证的 CORS 失败

Posted

技术标签:

【中文标题】在 Spring 服务器中使用 OAuth 身份验证的 CORS 失败【英文标题】:CORS failure with OAuth authentication in Spring server 【发布时间】:2016-02-27 06:38:06 【问题描述】:

当我尝试向调用“oauth/token”端点的 Spring 服务器进行身份验证时遇到 CORS 问题。 服务器以 401 响应响应

 XMLHttpRequest cannot load http://localhost:8080/oauth/token.
 Response to preflight request doesn't pass access control check: 
 No 'Access-Control-Allow-Origin' header is present on the requested resource. 
 Origin 'http://localhost:8000' is therefore not allowed access. 
 The response had HTTP status code 401.

这是我调用服务器的方式:

 login: function(credentials) 
        var data = "username=" +  encodeURIComponent(credentials.username) + "&password="
            + encodeURIComponent(credentials.password) + "&grant_type=password&scope=read%20write&" +
            "client_secret=mySecretOAuthSecret&client_id=awhyapp";
        return $http.post('http://localhost:8080/oauth/token', data, 
            headers: 
                "Content-Type": "application/x-www-form-urlencoded",
                "Accept": "application/json",
                "Access-Control-Allow-Origin": "*",
                "Authorization": "Basic " + Base64.encode("awhyapp" + ':' + "mySecretOAuthSecret")
            
        ).success(function (response) 
            var expiredAt = new Date();
            expiredAt.setSeconds(expiredAt.getSeconds() + response.expires_in);
            response.expires_at = expiredAt.getTime();
            localStorageService.set('token', response);
            return response;
        );

Oauth 配置:

 @Override
    public void configure(HttpSecurity http) throws Exception 
        http
            .authorizeRequests()
            .antMatchers(HttpMethod.OPTIONS, "/oauth/token").permitAll()
        .and()
            .exceptionHandling()
            .authenticationEntryPoint(authenticationEntryPoint)
        .and()
            .logout()
            .logoutUrl("/api/logout")
            .logoutSuccessHandler(ajaxLogoutSuccessHandler)
        .and()
            .csrf()
            .requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/authorize"))
            .disable()
            .headers()
            .frameOptions().disable()
        .and()
            .authorizeRequests()
            .antMatchers("/api/authenticate").permitAll()
            .antMatchers("/api/register").permitAll()
            .antMatchers("...").permitAll()
    

我遵循了这个问题 (Add headers to oauth/token response (spring-security)) 中的答案,但我的问题是,无论我如何配置我的 Filter 类,即使我使用 @Order 注释设置了最高优先级,这些函数也永远不会被调用。

【问题讨论】:

我遇到了完全相同的问题...您找到解决方法了吗? 【参考方案1】:

application.yml

中取消注释 cors
cors: #By default CORS are not enabled. Uncomment to enable.
        allowed-origins: "*"
        allowed-methods: GET, PUT, POST, DELETE, OPTIONS
        allowed-headers: "*"
        exposed-headers:
        allow-credentials: true
        max-age: 1800

当我遇到同样的错误时,这对我有用

【讨论】:

【参考方案2】:

Access-Control-Allow-Origin 在请求中是多余的。那是一个响应头。

在链接的答案中,将部分更改为: response.setHeader("Access-Control-Allow-Headers", "x-requested-with, Authorization, Accept, Content-Type"); 此更改列出了您将发送到服务器的请求中允许的标头值。

我不确定您的 spring 安全配置,但您基本上应该允许该端点上的 OPTIONS 请求无需身份验证即可工作。

祝你好运。

【讨论】:

我知道标头在请求中是无用的,但我试图使其无法正常工作...我对您的建议的问题是我的自定义过滤器类,它实现了 javax.servlet。当我调用 oauth/token 端点时,过滤器永远不会被调用,即使我给予的是 @Order 注释的最大优先级。 这是由于您的 spring 安全配置:它显然需要对每个调用进行身份验证,它应该允许 OPTIONS 请求。

以上是关于在 Spring 服务器中使用 OAuth 身份验证的 CORS 失败的主要内容,如果未能解决你的问题,请参考以下文章

Spring Cloud微服务安全实战_4-5_搭建OAuth2资源服务器

使用 Spring Security + WSO2 身份服务器的 OAuth 2.0

如何在 Spring Boot oauth2 资源服务器中使用自定义身份验证标头

在 Spring Security 中使用 Oauth2 手动进行身份验证不会在整个会话期间保持 SecurityContext

使用Spring启动进行Oauth2身份验证

Spring Boot - 使用 JWT、OAuth 以及单独的资源和身份验证服务器