2015-04-12 65 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 
     } 
    } 
}