OAuth2開發者指南—客戶端
引言
OAuth2.0客戶端機制負責訪問其他伺服器的OAuth2.0保護資源,配置包括建立相關受保護資源。客戶端也需要實現儲存使用者的授權程式碼和訪問令牌的功能。
受保護資源配置
受保護的資源(或稱為遠端資源)可以使用OAuth2ProtectedResourceDetails
型別的實體bean定義。一個受保護的資源有以下屬性:
- id
:資源id。它僅在客戶端搜尋資源的時候使用;在OAuth協議中它從未被用到。它也被用作bean的id。
- clientId
:OAuth客戶端id。OAuth提供端依賴這個id來識別客戶端。
- clientSecret
:與資源有關的客戶端金鑰,預設情況下其值不為空。
- accessTokenUri
-
scope
:以逗號分隔的字串列表,標識可訪問資源的範圍。預設情況下,該值為空。 -
clientAuthenticationScheme
:客戶端對訪問令牌端點進行身份驗證使用的方案,建議的值:httpbasic
和form
。預設值:http_basic
。參見OAuth 2規範的2.1節。。
不同的授權型別有不同的OAuth2ProtectedResourceDetails
介面的實現(對於client_credentials
授權型別,使用ClientCredentialsResource
)。對於需要進行使用者身份驗證的授權型別,還有一個屬性:
- userAuthorizationUri
在XML中,可以使用<resource/>
元素建立一個OAuth2ProtectedResourceDetails
型別的實體bean。它有上面提到的所有的屬性。
客戶端配置
對於OAuth 2.0客戶端,使用@EnableOAuth2Client
簡化了配置。主要做了兩件事:
- 建立一個過濾器bean(ID為oauth2ClientContextFilter
)來儲存當前請求和上下文。在請求期間需要進行身份驗證的情況下,它管理對OAuth身份驗證uri的重定向。
- 在請求作用域內建立AccessTokenRequest
這個過濾器需要能夠連線到應用(例如,使用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 id
和secret
——它們很容易在Facebook網站上生成)。
Facebook響應令牌也包含一個不一致的、有失效時間的JSON實體(他們使用expires
而不是expires_in
),所以如果你想在應用程式中使用超時時間你將不得不使用一個自定義OAuth2SerializationService
手動解碼。