为什么Spring Security permitAll()无法与OAuth2.0一起使用?

时间:2018-11-23 17:55:17

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

我有一个受OAuth2.0保护的REST API 我可以使用 http://localhost:8085/auth/token?grant_type=password&username=22@gmail.com&password=mypass (以及用户名通过基本身份验证)获得访问令牌。
但是,当我尝试访问 http://localhost:8085/api/v1/signup 时,API返回401 unauthorized错误。
尽管我使用过antMatchers("/signup").permitAll(),但API为什么期望access-token访问此资源?将access-token与该请求一起传递将注册用户。
这是我的资源服务器配置

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

//require beans and methods here

@Autowired
public void configureGlobal(final AuthenticationManagerBuilder auth) {
    auth.authenticationProvider(authProvider());
}

@Override
public void configure(final HttpSecurity http) throws Exception {
    http
    .authorizeRequests()
    .antMatchers("/signup").permitAll()
    .anyRequest().authenticated()
    .and()
    .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
    .csrf().disable();
}
}

更新:根据this线程的建议,我在``忽略了/signup,但这还是行不通的。

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
@ComponentScan(basePackages = { "com.sample.rest.security" })
@Order(2)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    //other Beans & methods

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        List<RequestMatcher> requestMatchers = new ArrayList<RequestMatcher>();
        requestMatchers.add(new AntPathRequestMatcher("/signup/**"));

        http.
        requestMatcher(new OrRequestMatcher(requestMatchers)).
        authorizeRequests().antMatchers("/signup/**")
        .permitAll();
    }

}

2 个答案:

答案 0 :(得分:2)

我知道了。导致问题的原因是上下文路径。我有一个使用映射URL /api/v1/*定义的调度程序servlet,正如我可以看到我的signup请求那样,它包含一个上下文路径,即http://localhost:8085/api/v1/signup

对于Spring中的OAuth2配置,我们需要特别注意上下文路径。首先,应在AuthorizationServer中定义

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
  @Override
  public void configure(final AuthorizationServerEndpointsConfigurer endpoints) { 
        endpoints
        .prefix("/api/v1") //here
        .tokenStore(tokenStore())
        .accessTokenConverter(accessTokenConverter())
        .authenticationManager(authenticationManager)
        .allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST);
  }

然后,必须将上下文这样添加到permitAll()路径

@Override
public void configure(final HttpSecurity http) throws Exception {
    http
    .authorizeRequests()
    .antMatchers("/api/v1/signup").permitAll()  //context path here
    .anyRequest().authenticated();
}

到目前为止,仍然希望注册请求将访问令牌与它一起传递。要从注册中删除OAuth安全性,我们需要在WebSecurity处删除安全性,这可以使用WebSecurityConfigurerAdapter

来完成。
@EnableWebSecurity
@EnableGlobalMethodSecurity
@ComponentScan(basePackages = { "com.sample.rest.security" })
public class SecurityConfig extends WebSecurityConfigurerAdapter {

     @Override
     public void configure(WebSecurity webSecurity) throws Exception {
        webSecurity.ignoring().antMatchers("/signup");
     }
 //////////// OR use below method ///////////
/*  @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.
        authorizeRequests().antMatchers("/signup/**").permitAll();
    }
*/
}

请注意,没有必要将上下文路径添加到WebSecurityConfigurerAdapter配置中。

答案 1 :(得分:0)

我认为订单是问题,匹配者是**。

@Override
public void configure(final HttpSecurity http) throws Exception {

 http    
   .authorizeRequests()
     .antMatchers("/signup**")
     .permitAll()
     .and()
   .authorizeRequests()
     .anyRequest()
     .authenticated()
     .and()
   .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() .csrf().disable();  

}