一、授權模式
1.1授權碼模式
下圖爲授權碼模式交互圖:
① 資源擁有者打開客戶端,客戶端要求資源擁有者給予授權,它將瀏覽器被重定向到授權服務器,重定向時會附加客戶端的身份信息。如:http://localhost:3001/oauth/authorize?client_id=c1&response_type=code&scope=all&redirect_uri=http://www.baidu.com
;
參數列表如下:
- client_id:客戶端准入標識
- response_type:授權碼模式固定爲
code
- scope:客戶端權限
- redirect_uri:跳轉
uri
,當授權碼申請成功後會跳轉到此地址,並在後邊帶上code
參數(授權碼)
②瀏覽器出現向授權服務器授權頁面,之後將用戶同意授權。
③授權服務器將授權碼(AuthorizationCode
)轉經瀏覽器發送給client
(通過redirect_uri
)
④客戶端拿着授權碼向授權服務器索要訪問access_token
,請求如下:http://localhost:3001/oauth/token? client_id=c1&client_secret=secret&grant_type=authorization_code&code=5PgfcD&redirect_uri=http://w ww.baidu.com
⑤授權服務器返回令牌(access_token
)
這種模式是四種模式中最安全的一種模式。一般用於client
是Web
服務器端應用或第三方的原生App
調用資源服務的時候。因爲在這種模式中access_token
不會經過瀏覽器或移動端的App
,而是直接從服務端去交換,這樣就最大限度的減小了令牌泄漏的風險。
測試:
瀏覽器訪問認證頁面:
http://localhost:3001/oauth/authorize?client_id=c1&response_type=code&scope=all&redirect_uri=http://www.baidu.com
然後輸入模擬的賬號和密碼點登陸之後進入授權頁面
確認授權後,瀏覽器會重定向到指定路徑並附帶授權碼,最後使用該授權碼獲取token。
獲取token
成功:
1.2簡化模式
下圖是簡化模式交互圖:
①資源擁有者打開客戶端,客戶端要求資源擁有者給予授權,它將瀏覽器被重定向到授權服務器,重定向時會 附加客戶端的身份信息。如:http://localhost:3001/oauth/authorize?client_id=c1&response_type=token&scope=all&redirect_uri=http://www.baidu.com
參數描述同授權碼模式 ,注意response_type=token
。
②瀏覽器出現向授權服務器授權頁面,之後將用戶同意授權。
③授權服務器將授權碼將令牌(access_token
)以Hash
的形式存放在重定向uri
的fragment
中發送給瀏覽器:
注:fragment
主要是用來標識URI
所標識資源裏的某個資源,在URI
的末尾通過(#)作爲 fragment
的開頭,js
通過響應瀏覽器地址欄變化的方式能獲取到fragment
就行了。
簡化模式用於沒有服務器端的第三方單頁面應用,因爲沒有服務器端就無法接收授權碼。
1.3密碼模式
下圖是密碼模式交互圖:
①資源擁有者將用戶名、密碼發送給客戶端
②客戶端拿着資源擁有者的用戶名、密碼向授權服務器請求令牌(access_token
),請求如下:http://localhost:3001/oauth/token? client_id=c1&client_secret=123&grant_type=password&username=admin&password=admin
;只支持POST
請求。
參數列表如下:
- client_id:客戶端准入標識
- client_secret:客戶端祕鑰
- grant_type:授權類型,
password
表示密碼模式 - username:資源擁有者用戶名
- password:資源擁有者密碼
③授權服務器將令牌(access_token
)發送給client
注:這種模式意味着直接將用戶敏感信息泄漏給了client
,因此這就說明這種模式只能用於client
是我們自己開發的情況下。因此密碼模式一般用於我們自己開發的,第一方原生App
或第一方單頁面應用。
1.4客戶端模式
下圖是客戶端模式交互圖:
①客戶端向授權服務器發送自己的身份信息,並請求令牌(access_token
)
②確認客戶端身份無誤後,將令牌(access_token)發送給client,請求如下:http://localhost:3001/oauth/token?client_id=c1&client_secret=123&grant_type=client_credentials
,支持POST
請求
參數列表如下:
- client_id:客戶端准入標識。
- client_secret:客戶端祕鑰。
- grant_type:授權類型,填寫
client_credentials
表示客戶端模式
注:這種模式是最方便但最不安全的模式。因此這就要求我們對client
完全的信任,而client
本身也是安全的。因此這種模式一般用來提供給我們完全信任的服務器端服務。比如,合作方系統對接,拉取一組用戶信息。
二、資源服務器
代碼和環境搭建忽略,詳情見:https://github.com/hucheng1997/security-oauth2
2.1 資源服務器配置
資源服務器配置類繼承ResourceServerConfigurerAdapter
重寫configure()
方法:
public class ResourceServerConfigurerAdapter implements ResourceServerConfigurer {
public ResourceServerConfigurerAdapter() {}
public void configure(ResourceServerSecurityConfigurer resources){}
public void configure(HttpSecurity http){}
}
參數爲ResourceServerSecurityConfigurer
的configure()
中主要配置:
- tokenServices:
ResourceServerTokenServices
類的實例,用來實現令牌服務 - tokenStore:
TokenStore
類的實例,指定令牌如何訪問,與tokenServices
配置可選 - resourceId:這個資源服務的
ID
,這個屬性是可選的,但是推薦設置並在授權服務中進行驗證。 - 其他的拓展屬性例如
tokenExtractor
令牌提取器用來提取請求中的令牌。
參數爲HttpSecurity
的configure()
中主要配置:
- 請求匹配器,用來設置需要進行保護的資源路徑,默認的情況下是保護資源服務的全部路徑。
- 通過
http.authorizeRequests()
來設置受保護資源的訪問規則 - 其他的自定義權限保護規則通過
HttpSecurity
來進行配置。
@EnableResourceServer 註解自動增加了一個類型爲OAuth2AuthenticationProcessingFilter
的過濾器鏈。
2.2 測試
申請令牌:
訪問資源:
使用錯誤的token
訪問資源: