Spring Boot 1.3.3 @EnableResourceServer和@ EnableOAuth2Sso同时进行

时间:2016-05-05 19:52:56

标签: spring spring-boot spring-security-oauth2

我希望我的服务器是ResourceServer,它可以接受承载访问令牌

但是,如果此类令牌不存在,我想使用OAuth2Server对我的用户进行身份验证。

我试着这样做:

@Configuration
@EnableOAuth2Sso
@EnableResourceServer
public class SecurityConfiguration extends WebSecurityConfigurerAdapter{

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().anyRequest().authenticated();
    }
}

但是,在这种情况下,只有@EnableResourceServer注释有效。它返回

Full authentication is required to access this resource

不要将我重定向到登录页面

我提到@Order很重要,如果我添加@Order(0)注释, 我将重定向到登录页面,但是,我无法使用Http标头中的access_token访问我的资源:

Authorization : Bearer 142042b2-342f-4f19-8f53-bea0bae061fc

我如何实现目标?我希望它同时使用Access令牌和SSO。

感谢〜

1 个答案:

答案 0 :(得分:12)

Using both configuration on same request would be ambiguous. There could be some solution for that, but more clear to define separate request groups:

  • OAuth2Sso: for users coming from a browser, we want to redirect them to the authentication provider for the token
  • ResourceServer: usually for api requests, coming with a token they got from somewhere (most probably from same authentication provider)

For achieving this, separate the configurations with request matcher:

@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

    @Bean("resourceServerRequestMatcher")
    public RequestMatcher resources() {
        return new AntPathRequestMatcher("/resources/**");
    }

    @Override
    public void configure(final HttpSecurity http) throws Exception {
        http
            .requestMatcher(resources()).authorizeRequests()
            .anyRequest().authenticated();
    }

}

And exclude these from the sso filter chain:

@Configuration
@EnableOAuth2Sso
public class SsoSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    @Qualifier("resourceServerRequestMatcher")
    private RequestMatcher resources;

    @Override
    protected void configure(final HttpSecurity http) throws Exception {
        RequestMatcher nonResoures = new NegatedRequestMatcher(resources);
        http
            .requestMatcher(nonResoures).authorizeRequests()
            .anyRequest().authenticated();
    }
}

And put all your resources under /resources/**

Of course in this case both will use the same oauth2 configuration (accessTokenUri, jwt.key-value, etc.)

UPDATE1:

Actually you can achieve your original goal by using this request matcher for the above configuration:

new RequestHeaderRequestMatcher("Authorization")

UPDATE2: (Explanation of @sid-morad's comment)

Spring Security creates a filter chain for each configuration. The request matcher for each filter chain is evaluated in the order of the configurations. WebSecurityConfigurerAdapter has default order 100, and ResourceServerConfiguration is ordered 3 by default. Which means ResourceServerConfiguration's request matcher evaluated first. This order can be overridden for these configurations like:

@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

    @Autowired
    private org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfiguration configuration;

    @PostConstruct
    public void setSecurityConfigurerOrder() {
        configuration.setOrder(3);
    }
...
}

 

@Configuration
@EnableOAuth2Sso
@Order(100)
public class SsoSecurityConfiguration extends WebSecurityConfigurerAdapter {
...
}

So yes, request matcher is not needed for SsoSecurityConfiguration in the above sample. But good to know the reasons behind :)