2017-02-18 48 views
4

我想为我的REST spring引导项目使用OAuth2。用一些例子,我创建配置的OAuth2:OAuth2与Spring Boot REST应用程序 - 不能使用令牌访问资源

@Configuration 
public class OAuth2Configuration { 

    private static final String RESOURCE_ID = "restservice"; 

    @Configuration 
    @EnableResourceServer 
    protected static class ResourceServerConfiguration extends 
      ResourceServerConfigurerAdapter { 

     @Override 
     public void configure(ResourceServerSecurityConfigurer resources) { 
      // @formatter:off 
      resources 
        .resourceId(RESOURCE_ID); 
      // @formatter:on 
     } 

     @Override 
     public void configure(HttpSecurity http) throws Exception { 
      // @formatter:off 
      http 
        .anonymous().disable() 
        .authorizeRequests().anyRequest().authenticated(); 
      // @formatter:on 
     } 

    } 

    @Configuration 
    @EnableAuthorizationServer 
    protected static class AuthorizationServerConfiguration extends 
      AuthorizationServerConfigurerAdapter { 

     private TokenStore tokenStore = new InMemoryTokenStore(); 

     @Autowired 
     @Qualifier("authenticationManagerBean") 
     private AuthenticationManager authenticationManager; 

     @Autowired 
     private UserDetailsServiceImpl userDetailsService; 

     @Override 
     public void configure(AuthorizationServerEndpointsConfigurer endpoints) 
      throws Exception { 
      // @formatter:off 
      endpoints 
        .tokenStore(this.tokenStore) 
        .authenticationManager(this.authenticationManager) 
        .userDetailsService(userDetailsService); 
      // @formatter:on 
     } 

     @Override 
     public void configure(ClientDetailsServiceConfigurer clients) throws Exception { 
      // @formatter:off 
      clients 
        .inMemory() 
        .withClient("clientapp") 
        .authorizedGrantTypes("password", "refresh_token", "trust") 
        .authorities("USER") 
        .scopes("read", "write") 
        .resourceIds(RESOURCE_ID) 
        .secret("clientsecret") 
        .accessTokenValiditySeconds(1200) 
        .refreshTokenValiditySeconds(3600); 
      // @formatter:on 
     } 

     @Bean 
     @Primary 
     public DefaultTokenServices tokenServices() { 
      DefaultTokenServices tokenServices = new DefaultTokenServices(); 
      tokenServices.setSupportRefreshToken(true); 
      tokenServices.setTokenStore(this.tokenStore); 
      return tokenServices; 
     } 
    } 
} 

这是我SecurityConfiguration类:

@Configuration 
@EnableWebSecurity 
@Order(1) 
public class SecurityConfiguration extends WebSecurityConfigurerAdapter { 

    @Autowired 
    private UserDetailsService userDetailsService; 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http.csrf().disable(); 
     http 
       .authorizeRequests().antMatchers("/api/register").permitAll() 
       .and() 
       .authorizeRequests().antMatchers("/api/free").permitAll() 
       .and() 
       .authorizeRequests().antMatchers("/oauth/token").permitAll() 
       .and() 
       .authorizeRequests().antMatchers("/api/secured").hasRole("USER") 
       .and() 
       .authorizeRequests().anyRequest().authenticated(); 
    } 

    @Override 
    @Bean 
    public AuthenticationManager authenticationManagerBean() throws Exception { 
     return super.authenticationManagerBean(); 
    } 

    @Bean 
    public PasswordEncoder passwordEncoder() { 
     return new BCryptPasswordEncoder(); 
    } 

} 

我试着用2级简单的要求来检查我的应用程序:

@RequestMapping(value = "/api/secured", method = RequestMethod.GET) 
public String checkSecured(){ 
    return "Authorization is ok"; 
} 

@RequestMapping(value = "/api/free", method = RequestMethod.GET) 
public String checkFree(){ 
    return "Free from authorization"; 
} 

首先我检查了两个请求:

/api/free返回

/API代码200和字符串 “从授权免费”/安全返回{ “时间戳”:1487451065106, “状态”:403, “错误”: “禁止”, “消息”:“访问否认“,”路径“:”/ api/secured“}

而且看起来它们工作正常。

然后我得到了ACCESS_TOKEN(使用我的用户数据库凭据)

/的OAuth /令牌grant_type =密码&用户名= EMAILA &密码= emailo

?回答:

{”的access_token “:” 3344669f-c66c-4161-9516-d7e2f31a32e8" , “token_type”: “承载”, “refresh_token”: “c71c17e4-45ba-458C-9d98-574de33d1859”, “expires_in”:1199, “范围”:”读写“}

然后我试图发送一个请求(与我得到的令牌),其要求认证为资源:

/API /固定的access_token = 3344669f-c66c-4161-9516-d7e2f31a32e8

这里是响应:

{ “时间戳”:1487451630224, “状态”:403, “错误”: “禁止”, “消息”: “拒绝访问”, “路径”: “/ API /固定”}

我不明白为什么访问被拒绝。我不确定在配置中,它似乎是不正确的。此外,我还没有清醒地认识方法的关系配置(HttpSecurity HTTP)在一个延伸WebSecurityConfigurerAdapter类和另一个延伸ResourceServerConfigurerAdapter。 谢谢你的帮助!

+0

当您发送令牌作为标题'Authorization:Bearer [TOKEN]'时会发生什么? – dav1d

+0

@ dav1d我试过但访问仍然被拒绝 – Alex

回答

19

如果您使用的是1.5.1或最近更新的弹簧引导,请注意他们更改了spring security oauth2(Spring Boot 1.5 Release Notes)的过滤顺序。

根据发行说明,尝试将以下属性添加到应用程序。性能/ YML,这样做的资源服务器过滤器将其他筛选器作为备用后使用后 - 这应该引起授权坠落到资源服务器之前被接受:

security.oauth2.resource.filter-order = 3 

你可以找到一个很好的答案为您的其他问题在这里:https://stackoverflow.com/questions/28537181

+0

非常感谢您的回答。我添加了这个属性并删除了@Order注解。现在我可以获取访问令牌,然后使用它获取/ api/secured资源。但现在我无法获得/ api/free。我认为它可以通过更改配置方法来解决。 – Alex

+0

很高兴帮助。如果它解决了您的问题,您可以将此答案标记为已接受。 – Tom

+0

是的,当然,它帮助了很多。 – Alex

相关问题