2015-04-12 175 views
15

我想获得一个使用Spring库运行的基本内存OAuth2服务器。我一直在关注sparklr example春季安全OAuth2资源服务器总是返回无效令牌

我目前已经配置了服务器,几乎所有的工作都正常,但是我无法从资源服务器访问我的受限资源。

我的测试流程:

  1. 访问授权URI的OAuth的开始OAuth2流程:http://localhost:8080/server/oauth/authorize?response_type=code&client_id=client

  2. 重定向到登录页面:http://localhost:8080/server/login

  3. 办理有关报批和重定向到我配置的重定向页面w /代码参数:http://localhost:8080/client?code=HMJO4K

  4. 构造一个使用该许可类型和代码沿着客户端ID和秘密使用基本身份验证的GET请求:http://localhost:8080/server/oauth/token?grant_type=authorization_code&code=HMJO4K

  5. ,接收和的access_token刷新令牌对象的回报

    { 的access_token:“f853bcc5-7801 -42d3-9cb8-303fc67b0453" token_type: “承载” refresh_token: “57100377-dea9-4df0-ADAB-62e33f2a1b49” expires_in:299 范围: “读写” }

  6. 尝试使用的access_token访问受限制的资源:http://localhost:8080/server/me?access_token=f853bcc5-7801-42d3-9cb8-303fc67b0453

  7. ,接收无效令牌回复

    { 错误: “INVALID_TOKEN” ERROR_DESCRIPTION:“无效访问令牌:f853bcc5-7801-42d3-9cb8-303fc67b0453 “ }

  8. POST令牌URI再度刷新令牌:http://localhost:8080/server/oauth/token?grant_type=refresh_token&refresh_token=57100377-dea9-4df0-adab-62e33f2a1b49

  9. 收到新令牌

    { 的access_token: “ed104994-899c-4cd9-8860-43d5689a9420” token_type: “承载” refresh_token: “57100377-dea9-4df0-ADAB-62e33f2a1b49” expires_in:300 范围: “读写” }

我真的不知道我做错了,但现在看来,比访问受限制的URI其他一切工作。这里是我的配置:

@Configuration 
public class Oauth2ServerConfiguration { 

    private static final String SERVER_RESOURCE_ID = "oauth2-server"; 

    @Configuration 
    @EnableResourceServer 
    protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { 

     @Override 
     public void configure(ResourceServerSecurityConfigurer resources) { 
      resources.resourceId(SERVER_RESOURCE_ID); 
     } 

     @Override 
     public void configure(HttpSecurity http) throws Exception { 
      http 
       .sessionManagement() 
        .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) 
       .and().requestMatchers() 
        .antMatchers("/me") 
       .and().authorizeRequests() 
        .antMatchers("/me").access("#oauth2.clientHasRole('ROLE_CLIENT')") 
      ; 
     } 
    } 

    @Configuration 
    @EnableAuthorizationServer 
    protected static class AuthotizationServerConfiguration extends AuthorizationServerConfigurerAdapter { 

     @Autowired 
     private ClientDetailsService clientDetailsService; 

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

     @Override 
     public void configure(ClientDetailsServiceConfigurer clients) throws Exception { 
      clients.inMemory() 
       .withClient("client") 
        .resourceIds(SERVER_RESOURCE_ID) 
        .secret("secret") 
        .authorizedGrantTypes("authorization_code", "refresh_token") 
        .authorities("ROLE_CLIENT") 
        .scopes("read","write") 
        .redirectUris("http://localhost:8080/client") 
        .accessTokenValiditySeconds(300) 
        .autoApprove(true) 
      ; 
     } 

     @Bean 
     public TokenStore tokenStore() { 
      return new InMemoryTokenStore(); 
     } 

     @Override 
     public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { 
      endpoints 
       .tokenStore(tokenStore()) 
       .userApprovalHandler(userApprovalHandler()) 
       .authenticationManager(authenticationManager) 
      ; 
     } 

     @Override 
     public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { 
      oauthServer.realm("oauth"); 
     } 

     @Bean 
     public ApprovalStore approvalStore() throws Exception { 
      TokenApprovalStore store = new TokenApprovalStore(); 
      store.setTokenStore(tokenStore()); 
      return store; 
     } 

     @Bean 
     public UserApprovalHandler userApprovalHandler() throws Exception { 
      TokenStoreUserApprovalHandler handler = new TokenStoreUserApprovalHandler(); 
      handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService)); 
      handler.setClientDetailsService(clientDetailsService); 
      handler.setTokenStore(tokenStore()); 

      return handler; 
     } 
    } 
} 

有什么我失踪或我接近这个不正确吗?任何帮助将不胜感激。

+0

一些测试后,我仍然无法得到它的工作。不知何故,似乎ResourceServer没有加载正确的令牌存储或其他东西。我有一个令牌存储bean并将它自动装配到一个控制器中,该控制器将打印我的客户端的令牌,这很好。我将同一令牌存储bean(使用唯一限定符)自动装入自定义身份验证管理器,并且无法在存储中找到任何托管。我真的不知道这是如何可能的,除非有隐含的会话范围? – jyore

回答

4

的问题结束了,资源服务器和授权服务器没有得到同样的道理存储参考。不知道接线如何不能正常工作,但在配置类中使用固定对象就像魅力一样工作。最终,我将转向持久性支持的令牌存储,这可能不会有任何问题。

感谢@OhadR的回答和帮助!

最后,我简单的配置,就通了相同的工作流程,并制定出

@Configuration 
public class Oauth2ServerConfiguration { 

    private static final String SERVER_RESOURCE_ID = "oauth2-server"; 

    private static InMemoryTokenStore tokenStore = new InMemoryTokenStore(); 


    @Configuration 
    @EnableResourceServer 
    protected static class ResourceServer extends ResourceServerConfigurerAdapter { 

     @Override 
     public void configure(ResourceServerSecurityConfigurer resources) throws Exception { 
      resources.tokenStore(tokenStore).resourceId(SERVER_RESOURCE_ID); 
     } 

     @Override 
     public void configure(HttpSecurity http) throws Exception { 
      http.requestMatchers().antMatchers("/me").and().authorizeRequests().antMatchers("/me").access("#oauth2.hasScope('read')"); 
     } 
    } 

    @Configuration 
    @EnableAuthorizationServer 
    protected static class AuthConfig extends AuthorizationServerConfigurerAdapter { 

     @Autowired 
     private AuthenticationManager authenticationManager; 


     @Override 
     public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { 
      endpoints.authenticationManager(authenticationManager).tokenStore(tokenStore).approvalStoreDisabled(); 
     } 

     @Override 
     public void configure(ClientDetailsServiceConfigurer clients) throws Exception { 
      clients.inMemory() 
       .withClient("client") 
        .authorizedGrantTypes("authorization_code","refresh_token") 
        .authorities("ROLE_CLIENT") 
        .scopes("read") 
        .resourceIds(SERVER_RESOURCE_ID) 
        .secret("secret") 
      ; 
     } 
    } 
} 

任何人在这个职位上绊倒,我建议在单元测试示例,而不是完全成熟寻找更多sparklr/tonr的例子,因为它有很多额外的配置,不一定需要入门。

+0

感谢张贴这个问题和答案。它帮助我对此进行了自己的研究。你应该将OhadR的回答标记为正确答案,因为他让你得出了正确的结论。 – pacman

+0

我恳请你的答案涉及一个'AuthorizationServerConfigurerAdapter'。我在Spring OAuth2应用程序中收到'org.springframework.security.oauth2.provider.NoSuchClientException'错误,这似乎是由我的'AuthorizationServerConfigurerAdapter'导致的。你愿意看看吗?这里是链接:http://stackoverflow.com/questions/36899386/connecting-a-clientdetailsservice-to-a-custom-oauth2requestfactory – CodeMed

+0

我在线,如果你愿意给我一个暗示其他问题。不知道从哪里开始。 – CodeMed

4

您的第6步是错误的 - 访问令牌不应该在URL中发送,因为它以这种方式受到攻击。比GET更容易,使用POST。

此外,我不明白你的第一步 - 为什么你打电话给/ oauth /授权?当您尝试获取受保护的资源时,应该隐式地完成它。我的意思是,你的流量应先从:

Attempt to access a restricted resource using the access_token: http://localhost:8080/server/me

那么谈判将启动“幕后”:一个重定向到“/ OAuth的/授权”等

此外,在步骤#8,请注意,您并不是要求“另一个访问令牌”,而是它是“刷新令牌”的请求。就好像您的访问令牌已过期。

注意:身份提供者和资源服务器应共享tokenStore!在这里阅读:Spring Security OAuth2 pure resource server

HTH

+0

感谢您的回复。尝试访问资源服务器时,我尝试了GET&POST。我曾尝试以查询参数,表单数据的形式发送,并将其作为标题“授权:承载者”进行发送,并且在每种情况下,我都会继续收到“无效标记”响应。我已经设置了一些调试端点来转储客户端和用户的当前令牌,并且我的令牌位于两个列表中。 – jyore

+0

资源服务器必须知道如何解析令牌......您是否编写了受保护的资源? – OhadR

+0

这个资源只是一个spring-mvc端点设置,通过@RequestMapping(“/ me”)返回一个json字符串@ResponseBody public String me(){return“hello”;}'。 'org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter'拒绝这个标记。自发布以来,我试着将'ResourceServerSecurityConfirer'的配置添加到'TokenStore'和'TokenServices' bean的引用中,这两者都没有奏效。 – jyore

0

这个工作对我来说:

@Configuration 
public class Oauth2ServerConfiguration { 

    private static final String SERVER_RESOURCE_ID = "oauth2-server"; 

    @Autowired 
    private TokenStore tokenStore; 

    @Bean 
    public TokenStore tokenStore() { 
     return new InMemoryTokenStore(); 
    } 

    @Configuration 
    @EnableResourceServer 
    protected static class ResourceServer extends ResourceServerConfigurerAdapter { 

     @Override 
     public void configure(ResourceServerSecurityConfigurer resources) throws Exception { 
      resources.tokenStore(tokenStore).resourceId(SERVER_RESOURCE_ID); 
     } 

     @Override 
     public void configure(HttpSecurity http) throws Exception { 
      // ... Not important at this stage 
     } 
    } 

    @Configuration 
    @EnableAuthorizationServer 
    protected static class AuthConfig extends AuthorizationServerConfigurerAdapter { 

     @Autowired 
     private AuthenticationManager authenticationManager; 


     @Override 
     public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { 
      endpoints.authenticationManager(authenticationManager).tokenStore(tokenStore).approvalStoreDisabled(); 
     } 

     @Override 
     public void configure(ClientDetailsServiceConfigurer clients) throws Exception { 
      //... Not important at this stage 
     } 
    } 
}