独立 Spring OAuth2 JWT 授权服务器 + CORS [英] Standalone Spring OAuth2 JWT Authorization Server + CORS

查看:32
本文介绍了独立 Spring OAuth2 JWT 授权服务器 + CORS的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我从 这个例子来自 Dave Syer

So I have the following Authorization Server condensed from this example from Dave Syer

@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 测试时

when I run it and test it with 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 错误.不是因为缺少标题,而是因为 OPTION 请求被拒绝并且缺少凭据.

I get a JWT as respons, but as soon as I try to access the AuthServer from my Frontend (Angular JS on a different port) I get CORS error. Not becauce of missing Headers, but because the OPTION request is rejected and is missing the credentials.

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 并且另外发现 在这篇文章中,我使用了第一个答案的片段,让 OPTIONS 请求无需凭据即可访问 /oauth/token:

I already knew that I have to add a CorsFilter and additionally found this post where I used the the snippet for the first Answer to let the OPTIONS request access /oauth/token without credentials:

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

之后我用 curl 得到以下错误:

After that I got with curl the following error:

{"timestamp":1433370068120,"status":403,"error":"Forbidden","message":"Expected CSRF token not found. Has your session expired?","path":"/oauth/token"}

为了简单起见,我只是将 http.csrf().disable() 添加到 MyWebSecurity 类的 configure 方法中,这解决了 OPTION 请求的问题,但因此 POST 请求不再起作用,我得到 没有客户端身份验证.尝试添加适当的身份验证过滤器.(也使用 curl).

So to make it simple I just added http.csrf().disable() to the configure method of MyWebSecurity class, which solves the Problem with the OPTION request, but therefore the POST request isn't working anymore and I get There is no client authentication. Try adding an appropriate authentication filter. (also with curl).

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

I tried to find out if I have to somehow connect MyWebSecurity class and the AuthServer, but without any luck. The original example (link in the beginning) injects as well the authenticationManager, but this changed nothing for me.

推荐答案

找到我的问题的原因!

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

I just needed to end the filterchain and return the result immediatly if a OPTIONS request is processed by the CorsFilter!

SimpleCorsFilter.java

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 预检请求

After that I could ignore the OPTIONS preflight request in my AuthServer =D

因此服务器的工作方式与上面的片段相同,您可以在开头使用 MyWebSecurity 类忽略块注释.

So the Server works as in the snipped above and you can ignore the block comment with MyWebSecurity class in the beginning.

这篇关于独立 Spring OAuth2 JWT 授权服务器 + CORS的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆