1. 程式人生 > >OAuth2開發者指南—客戶端

OAuth2開發者指南—客戶端

引言

OAuth2.0客戶端機制負責訪問其他伺服器的OAuth2.0保護資源,配置包括建立相關受保護資源。客戶端也需要實現儲存使用者的授權程式碼和訪問令牌的功能。

受保護資源配置

受保護的資源(或稱為遠端資源)可以使用OAuth2ProtectedResourceDetails型別的實體bean定義。一個受保護的資源有以下屬性:
- id:資源id。它僅在客戶端搜尋資源的時候使用;在OAuth協議中它從未被用到。它也被用作bean的id。
- clientId:OAuth客戶端id。OAuth提供端依賴這個id來識別客戶端。
- clientSecret:與資源有關的客戶端金鑰,預設情況下其值不為空。
- accessTokenUri

:提供訪問令牌的提供者OAuth端點的URI。
- scope:以逗號分隔的字串列表,標識可訪問資源的範圍。預設情況下,該值為空。
- clientAuthenticationScheme:客戶端對訪問令牌端點進行身份驗證使用的方案,建議的值:httpbasicform。預設值:http_basic。參見OAuth 2規範的2.1節。。

不同的授權型別有不同的OAuth2ProtectedResourceDetails介面的實現(對於client_credentials授權型別,使用ClientCredentialsResource )。對於需要進行使用者身份驗證的授權型別,還有一個屬性:
- userAuthorizationUri

:使用者訪問資源需要身份驗證時跳轉頁面的URI。 注意這個欄位不是必填的,它依賴於被支援的OAuth 2的配置檔案型別。

在XML中,可以使用<resource/>元素建立一個OAuth2ProtectedResourceDetails型別的實體bean。它有上面提到的所有的屬性。

客戶端配置

對於OAuth 2.0客戶端,使用@EnableOAuth2Client簡化了配置。主要做了兩件事:
- 建立一個過濾器bean(ID為oauth2ClientContextFilter)來儲存當前請求和上下文。在請求期間需要進行身份驗證的情況下,它管理對OAuth身份驗證uri的重定向。
- 在請求作用域內建立AccessTokenRequest

型別的bean。這可以由使用授權程式碼(或隱式)授權模式的客戶端使用,以防止與個別使用者發生衝突。

這個過濾器需要能夠連線到應用(例如,使用Servlet初始化程式或者web.xml配置檔案配置一個和DelegatingFilterProxy相同名稱的代理)。

這個AccessTokenRequest可以在OAuth2RestTemplate中使用:

@Autowired
private OAuth2ClientContext oauth2Context;

@Bean
public OAuth2RestTemplate sparklrRestTemplate() {
    return new OAuth2RestTemplate(sparklr(), oauth2Context);
}

例項OAuth2ClientContext可以在Session的作用域中保持不同使用者不同的狀態。否則,您將不得不在伺服器上管理相同的資料結構,將傳入的請求對映到使用者,並將每個使用者與OAuth2ClientContext的單獨例項關聯起來。

在XML中有一個帶有id屬性的<client/>標籤用於表示servlet的Filter的bean id素——這是servlet Filter的bean id,它必須被對映到一個DelegatingFilterProxy(具有相同的名稱)的@Configuration註解。

訪問受保護資源

一旦您為這些資源提供了所有配置,現在就可以訪問這些資源了。訪問這些資源的建議方法是使用在Spring 3中引入的RestTemplate。Spring Security OAuth 已經提供了一個擴充套件的RestTemplate只需要提供OAuth2ProtectedResourceDetails的例項。
要將它與user-tokens(授權碼模式)一起使用,您應該考慮使用@EnableOAuth2Client配置(或者是XML配置<oauth:rest-template/>),它建立了一些請求和會話範圍的上下文物件,以便不同使用者的請求在執行時不會發生衝突。

一般來說,一個web應用程式不應該使用密碼模式,所以如果你能支援AuthorizationCodeResourceDetails的話,儘量避免使用ResourceOwnerPasswordResourceDetails。如果您非常需要在Java客戶端中使用密碼模式,那麼使用相同的機制來配置您的OAuth2RestTemplate並將憑據新增到AccessTokenRequest(短暫的Map)而不是ResourceOwnerPasswordResourceDetails(在所有訪問令牌之間共享)。

客戶端持久化訪問令牌

客戶端不需要持久化令牌,但對於使用者來說,每次重新啟動客戶端應用程式時都不需要批准新的令牌授權,這是一項很人性化的功能。ClientTokenServices介面定義了為特定使用者持久化OAuth 2.0令牌所必需的操作。這裡提供了一個JDBC實現,但是如果您喜歡的話,也可以自己實現一個服務,將訪問令牌和相關的身份驗證例項儲存在持久化資料庫中。如果您想要使用這個功能,您需要為OAuth2RestTemplate提供一個特殊配置的TokenProvider。eg:

@Bean
@Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES)
public OAuth2RestOperations restTemplate() {
    OAuth2RestTemplate template = new OAuth2RestTemplate(resource(), new DefaultOAuth2ClientContext(accessTokenRequest));
    AccessTokenProviderChain provider = new AccessTokenProviderChain(Arrays.asList(new AuthorizationCodeAccessTokenProvider()));
    provider.setClientTokenServices(clientTokenServices());
    return template;
}

為外部 OAuth2 提供者定製客戶端

一些外部的OAuth2提供者(例如facebook)並沒有正確地實現規範,或者他們只是停留在一個較老版本的規範上,而不是Spring Security OAuth。要在客戶端應用程式中使用這些外部提供者,您可能需要調整客戶端基礎結構的各個部分。

如果要使用Facebook作為例子,在tonr2應用程式中有一個Facebook的例子作為參考(您需要更改配置來新增您自己的、有效的、client idsecret——它們很容易在Facebook網站上生成)。

Facebook響應令牌也包含一個不一致的、有失效時間的JSON實體(他們使用expires而不是expires_in),所以如果你想在應用程式中使用超時時間你將不得不使用一個自定義OAuth2SerializationService手動解碼。