spring-security - 独立 Spring OAuth2 JWT 授权服务器 + CORS

标签 spring-security cors jwt spring-security-oauth2

所以我有以下从 this example 浓缩的授权服务器来自戴夫·赛尔

@SpringBootApplication
public class AuthserverApplication {

    public static void main(String[] args) {
            SpringApplication.run(AuthserverApplication.class, args);
    }

    /* added later
    @Configuration
    @Order(Ordered.HIGHEST_PRECEDENCE)
    protected static class MyWebSecurity extends WebSecurityConfigurerAdapter {

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http //.csrf().disable() 
                .authorizeRequests()
                .antMatchers(HttpMethod.OPTIONS, "/oauth/token").permitAll();
       }
    }*/

    @Configuration
    @EnableAuthorizationServer
    protected static class OAuth2AuthorizationConfig extends
                    AuthorizationServerConfigurerAdapter {

            @Autowired
            private AuthenticationManager authenticationManager;

            @Bean
            public JwtAccessTokenConverter jwtAccessTokenConverter() {
                    JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
                    KeyPair keyPair = new KeyStoreKeyFactory(
                                    new ClassPathResource("keystore.jks"), "foobar".toCharArray())
                                    .getKeyPair("test");
                    converter.setKeyPair(keyPair);
                    return converter;
            }

            @Override
            public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
                    clients.inMemory()
                                    .withClient("acme")
                                    //.secret("acmesecret")
                                    .authorizedGrantTypes(//"authorization_code", "refresh_token",
                                                    "password").scopes("openid");
            }

            @Override
            public void configure(AuthorizationServerEndpointsConfigurer endpoints)
                            throws Exception {
                    endpoints.authenticationManager(authenticationManager).accessTokenConverter(
                                    jwtAccessTokenConverter());
            }

            @Override
            public void configure(AuthorizationServerSecurityConfigurer oauthServer)
                            throws Exception {
                    oauthServer.tokenKeyAccess("permitAll()").checkTokenAccess(
                                    "isAuthenticated()");
            }
    }
}

当我运行它并用 curl 测试它时
curl acme@localhost:8110/oauth/token -d grant_type=password -d client_id=acme -d username=user -d password=password

我得到一个 JWT 作为响应,但是当我尝试从我的前端(不同端口上的 Angular JS)访问 AuthServer 时,我得到了 CORS 错误。不是因为缺少 header ,而是因为 OPTION 请求被拒绝并且缺少凭据。
Request URL:http://localhost:8110/oauth/token
Request Method:OPTIONS
Status Code:401 Unauthorized
WWW-Authenticate:Bearer realm="oauth", error="unauthorized", error_description="Full authentication is required to access this resource"

我已经知道我必须添加一个 CorsFilter 并且另外发现了 this post我使用第一个答案的片段来让 OPTIONS 请求访问 /oauth/token没有凭据:

@Order(-1)
public class MyWebSecurity extends WebSecurityConfigurerAdapter {
   @Override
   protected void configure(HttpSecurity http) throws Exception {
       http
          .authorizeRequests()
          .antMatchers(HttpMethod.OPTIONS, "/oauth/token").permitAll();
   }
}

之后,我得到了 curl 以下错误:
{"timestamp":1433370068120,"status":403,"error":"Forbidden","message":"Expected CSRF token not found. Has your session expired?","path":"/oauth/token"}

所以为了简单起见,我只是添加了http.csrf().disable()configure MyWebSecurity 类的方法,它解决了 OPTION 请求的问题,但因此 POST 请求不再工作,我得到 There is no client authentication. Try adding an appropriate authentication filter. (也有 curl )。

我试图找出是否必须以某种方式连接 MyWebSecurity 类和 AuthServer,但没有任何运气。原始示例(开头的链接)也注入(inject)了 authenticationManager,但这对我来说没有任何改变。

最佳答案

找到了我的问题的原因!

如果 CorsFilter 处理了 OPTIONS 请求,我只需要结束过滤器链并立即返回结果!

SimpleCorsFilter.java

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class SimpleCorsFilter implements Filter {

    public SimpleCorsFilter() {
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        HttpServletRequest request = (HttpServletRequest) req;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with, authorization");

        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
        } else {
            chain.doFilter(req, res);
        }
    }

    @Override
    public void init(FilterConfig filterConfig) {
    }

    @Override
    public void destroy() {
    }
}

之后,我可以忽略 AuthServer =D 中的 OPTIONS 预检请求

所以服务器就像上面的截图一样工作,你可以在开始时忽略 MyWebSecurity 类的 block 注释。

关于spring-security - 独立 Spring OAuth2 JWT 授权服务器 + CORS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30632200/

相关文章:

api - OPTIONS 请求使应用程序变慢 2 倍?

c# - 如何使用.Net Core验证KeyCloak提供的JWT?

node.js - twilio 视频访问 token 过期后会发生什么?

javascript - 添加文档访问被拒绝

encryption - 如何从 RSA JWK 中提取公钥和私钥?

java - 定义具体方法的接口(interface) - 在什么情况下允许这样做?

java - Spring SAML中指定IDP和SP的加密算法

java - 在 Spring Security 中设置自定义身份验证和角色

java - Maven 中的 Spring Security 4.0.0?

c# - 在 AngularJS/WebApi 应用程序中使用 Windows 身份验证的 CORS 问题 - 仅适用于 IE