Spring security oauth2-客戶端模式,簡化模式,密碼模式(Finchley版本)
一、客戶端模式原理解析(來自理解OAuth 2.0)
客戶端模式(Client Credentials Grant)指客戶端以自己的名義,而不是以使用者的名義,向"服務提供商"進行認證。嚴格地說,客戶端模式並不屬於OAuth框架所要解決的問題。在這種模式中,使用者直接向客戶端註冊,客戶端以自己的名義要求"服務提供商"提供服務,其實不存在授權問題。
具體步驟:
- (A) 客戶端向認證伺服器進行身份認證,並要求一個訪問令牌。請求的引數如下:
- response_type:表示授權型別,必選項,此處的值固定為"client_credentials"
- client_id:表示客戶端的ID,必選項
- client_secret:客戶端的密碼,可選項
- scope:表示申請的許可權範圍,可選項
POST /token HTTP/1.1 Host: server.example.com Content-Type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=s6BhdRkqt3 &client_secret=123456&scope=test
- (B) 認證伺服器確認無誤後,向客戶端提供訪問令牌
1.1 客戶端模式示例
本節在
1.1.1 修改授權服務
修改授權服務配置類AuthorizationServerConfiguration
,在客戶端詳情配置中新增客戶端模式配置:
/**
* 配置客戶端詳情服務
* 客戶端詳細資訊在這裡進行初始化,你能夠把客戶端詳情資訊寫死在這裡或者是通過資料庫來儲存調取詳情資訊
* @param clients
* @throws Exception
*/
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("client1")//用於標識使用者ID
.authorizedGrantTypes("authorization_code","client_credentials","refresh_token")//授權方式
.scopes("test")//授權範圍
.secret(PasswordEncoderFactories.createDelegatingPasswordEncoder().encode("123456"));//客戶端安全碼,secret密碼配置從 Spring Security 5.0開始必須以 {bcrypt}+加密後的密碼 這種格式填寫;
}
其它地方無需修改
1.1.2 測試
啟動授權服務和資源服務。
- 獲取token
使用postman工具傳送post請求返回結果如下:{ "access_token":"69b10f69-0a99-4925-b81d-f83c6f79d32a", "token_type":"bearer", "expires_in":42600, "scope":"test" }
- 獲取資源
使用postman工具傳送get請求http://localhost:8088/user?access_token=69b10f69-0a99-4925-b81d-f83c6f79d32a
返回結果如下:{ "authorities": [], "details": { "remoteAddress": "0:0:0:0:0:0:0:1", "sessionId": null, "tokenValue": "69b10f69-0a99-4925-b81d-f83c6f79d32a", "tokenType": "Bearer", "decodedDetails": null }, "authenticated": true, "userAuthentication": null, "principal": "client1", "credentials": "", "clientOnly": true, "oauth2Request": { "clientId": "client1", "scope": [ "test" ], "requestParameters": { "client_id": "client1" }, "resourceIds": [], "authorities": [], "approved": true, "refresh": false, "redirectUri": null, "responseTypes": [], "extensions": {}, "grantType": null, "refreshTokenRequest": null }, "name": "client1" }
二、密碼模式原理解析(來自理解OAuth 2.0)
密碼模式(Resource Owner Password Credentials Grant)中,使用者向客戶端提供自己的使用者名稱和密碼。客戶端使用這些資訊,向"服務商提供商"索要授權。
在這種模式中,使用者必須把自己的密碼給客戶端,但是客戶端不得儲存密碼。這通常用在使用者對客戶端高度信任的情況下,比如客戶端是作業系統的一部分,或者由一個著名公司出品。而認證伺服器只有在其他授權模式無法執行的情況下,才能考慮使用這種模式。
具體步驟如下:
- (A) 使用者向客戶端提供使用者名稱和密碼。
- (B) 客戶端將使用者名稱和密碼發給認證伺服器,向後者請求令牌。請求引數如下:
- grant_type:表示授權型別,此處的值固定為"password",必選項
- username:表示使用者名稱,必選項
- password:表示使用者的密碼,必選項
- client_id:表示客戶端的ID,必選項
- client_secret:表示客戶端密碼,可選項
- scope:表示許可權範圍,可選項。
- © 認證伺服器確認無誤後,向客戶端提供訪問令牌。
整個過程中,客戶端不得儲存使用者的密碼。
2.1 密碼模式示例
本節在Spring Security Oauth2-授權碼模式(Finchley版本)做很小的修改就可以實現客戶端模式。密碼模式為為遺留系統設計,支援refresh token。
1.1.1 修改授權服務
修改授權服務配置類AuthorizationServerConfiguration
,在客戶端詳情配置中新增密碼模式配置:
/**
* 配置客戶端詳情服務
* 客戶端詳細資訊在這裡進行初始化,你能夠把客戶端詳情資訊寫死在這裡或者是通過資料庫來儲存調取詳情資訊
* @param clients
* @throws Exception
*/
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("client1")//用於標識使用者ID
.authorizedGrantTypes("authorization_code","client_credentials","password","refresh_token")//授權方式
.scopes("test")//授權範圍
.secret(PasswordEncoderFactories.createDelegatingPasswordEncoder().encode("123456"));//客戶端安全碼,secret密碼配置從 Spring Security 5.0開始必須以 {bcrypt}+加密後的密碼 這種格式填寫;
}
其它地方無需修改
2.2 測試
啟動授權服務和資源服務。
- 獲取token
使用postman工具傳送post請求返回結果如下:{ "access_token": "9411d111-141f-441f-83d2-af7be239509c", "token_type": "bearer", "refresh_token": "196fc388-3d46-4133-966d-e840063f426a", "expires_in": 43179, "scope": "test" }
- 獲取資源
使用postman工具傳送get請求http://localhost:8088/user?access_token=9411d111-141f-441f-83d2-af7be239509c
返回結果如下:{ "authorities": [ { "authority": "USER" } ], "details": { "remoteAddress": "0:0:0:0:0:0:0:1", "sessionId": null, "tokenValue": "9411d111-141f-441f-83d2-af7be239509c", "tokenType": "Bearer", "decodedDetails": null }, "authenticated": true, "userAuthentication": { "authorities": [ { "authority": "USER" } ], "details": null, "authenticated": true, "principal": "admin", "credentials": "N/A", "name": "admin" }, "principal": "admin", "credentials": "", "clientOnly": false, "oauth2Request": { "clientId": "client1", "scope": [ "test" ], "requestParameters": { "client_id": "client1" }, "resourceIds": [], "authorities": [], "approved": true, "refresh": false, "redirectUri": null, "responseTypes": [], "extensions": {}, "grantType": null, "refreshTokenRequest": null }, "name": "admin" }
三、簡化模式原理解析(來自理解OAuth 2.0)
簡化模式(implicit grant type)不通過第三方應用程式的伺服器,直接在瀏覽器中向認證伺服器申請令牌,跳過了"授權碼"這個步驟,因此得名。所有步驟在瀏覽器中完成,令牌對訪問者是可見的,且客戶端不需要認證。
具體步驟如下:
- (A) 客戶端將使用者導向認證伺服器。請求引數如下:
- response_type:表示授權型別,此處的值固定為"token",必選項。
- client_id:表示客戶端的ID,必選項。
- redirect_uri:表示重定向的URI,可選項。
- scope:表示許可權範圍,可選項。
- state:表示客戶端的當前狀態,可以指定任意值,認證伺服器會原封不動地返回這個值。
- (B) 使用者決定是否給於客戶端授權。
- © 假設使用者給予授權,認證伺服器將使用者導向客戶端指定的"重定向URI",並在URI的Hash部分包含了訪問令牌,其引數如下:
- access_token:表示訪問令牌,必選項。
- token_type:表示令牌型別,該值大小寫不敏感,必選項。
- expires_in:表示過期時間,單位為秒。如果省略該引數,必須其他方式設定過期時間。
- scope:表示許可權範圍,如果與客戶端申請的範圍一致,此項可省略。
- state:如果客戶端的請求中包含這個引數,認證伺服器的迴應也必須一模一樣包含這個引數。
- (D) 瀏覽器向資源伺服器發出請求,其中不包括上一步收到的Hash值。
- (E) 資源伺服器返回一個網頁,其中包含的程式碼可以獲取Hash值中的令牌。
- (F) 瀏覽器執行上一步獲得的指令碼,提取出令牌。
- (G) 瀏覽器將令牌發給客戶端。
3.1 簡化模式示例:
本節在Spring Security Oauth2-授權碼模式(Finchley版本)做很小的修改就可以實現客戶端模式。簡化模式為web瀏覽器應用設計,支援refresh token,比授權碼模式少了code環節,回撥url直接攜帶token,基於安全性考慮,建議把token時效設定短一些。
1.1.1 修改授權服務
修改授權服務配置類AuthorizationServerConfiguration
,在客戶端詳情配置中新增簡化模式配置:
/**
* 配置客戶端詳情服務
* 客戶端詳細資訊在這裡進行初始化,你能夠把客戶端詳情資訊寫死在這裡或者是通過資料庫來儲存調取詳情資訊
* @param clients
* @throws Exception
*/
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("client1")//用於標識使用者ID
.authorizedGrantTypes("authorization_code","client_credentials","password","implicit","refresh_token")//授權方式
.scopes("test")//授權範圍
.secret(PasswordEncoderFactories.createDelegatingPasswordEncoder().encode("123456"));//客戶端安全碼,secret密碼配置從 Spring Security 5.0開始必須以 {bcrypt}+加密後的密碼 這種格式填寫;
}
其它地方無需修改
2.2 測試
啟動授權服務和資源服務。
- 獲取token
使用瀏覽器傳送get請求http://localhost:8080/oauth/authorize?response_type=token&client_id=client1&redirect_uri=https://screenshot.net/zh/free-image-uploader.html
,使用者輸入密碼並授權後瀏覽器的重定向地址為https://screenshot.net/zh/free-image-uploader.html#access_token=ab7b3a82-9b0d-4346-8603-da35891c26f2&token_type=bearer&expires_in=42111&scope=test
,其中包含了token - 獲取資源
使用postman工具傳送get請求http://localhost:8088/user?access_token=ab7b3a82-9b0d-4346-8603-da35891c26f2
返回結果如下:{ "authorities": [ { "authority": "USER" } ], "details": { "remoteAddress": "0:0:0:0:0:0:0:1", "sessionId": null, "tokenValue": "ab7b3a82-9b0d-4346-8603-da35891c26f2", "tokenType": "Bearer", "decodedDetails": null }, "authenticated": true, "userAuthentication": { "authorities": [ { "authority": "USER" } ], "details": null, "authenticated": true, "principal": "admin", "credentials": "N/A", "name": "admin" }, "principal": "admin", "credentials": "", "clientOnly": false, "oauth2Request": { "clientId": "client1", "scope": [ "test" ], "requestParameters": { "client_id": "client1" }, "resourceIds": [], "authorities": [], "approved": true, "refresh": false, "redirectUri": null, "responseTypes": [], "extensions": {}, "grantType": null, "refreshTokenRequest": null }, "name": "admin" }