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

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

问题描述

因此,我有以下授权服务器从此示例来自Dave Syer

  @ SpringBootApplication 
public class AuthserverApplication {

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

/ *稍后添加
@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
受保护的静态类OAuth2AuthorizationConfig扩展
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(ClientDetailsS​​erviceConfigurer 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());
}
}
}

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错误。

 请求网址:http:// 

localhost:8110 / oauth / token
请求方法:OPTIONS
状态代码:401未授权
WWW验证:承载realm =oauth,error =未授权,error_description =完全验证需要访问此资源

我已经知道我必须添加一个CorsFilter, a href =http://stackoverflow.com/questions/25136532/allow-options-http-method-for-oauth-token-request>此帖子,其中我使用第一个答案的代码段让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();
}
}

之后,我遇到了以下错误: / p>

  {timestamp:1433370068120,status:403,error:Forbidden,message:未找到CSRF令牌。您的会话是否已过期?,path:/ oauth / token} 

为了使它简单我只是添加 http.csrf()。disable() configure MyWebSecurity类,它解决了OPTION请求的问题,因此POST请求不再工作,我得到没有客户端身份验证。尝试添加一个适当的验证过滤器。(也与curl)。



我试图找出是否要以某种方式连接MyWebSecurity类和AuthServer,但没有任何运气。原始示例(链接在开头)注入以及authenticationManager,但这没有改变我。

解决方案

找到我的问题的原因!



结束filterchain并立即返回结果,如果OPTIONS请求由CorsFilter处理!



SimpleCorsFilter.java



< pre class =lang-java prettyprint-override> @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中的OPTIONS预检请求$ <$ p

因此,服务器的工作方式与上面的截图相同,您可以在开始时使用MyWebSecurity类忽略块注释。 p>

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()");
            }
    }
}

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

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"

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();
   }
}

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"}

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).

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.

解决方案

Found the reason for my Problem!

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

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() {
    }
}

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

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天全站免登陆