SpringBoot + Spring Security OAuth2基本使用
OAuth2.0基本知識
網上關於OAuth2.0的介紹已經很多了,這裡就不做過多的介紹,不太瞭解的朋友可以參考理解OAuth 2.0
Spring Security OAuth2
基本配置
這裡依然使用maven來做管理
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
</dependency>
<dependency >
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency >
認證伺服器
在過OAuth2.0有了基本概念後,我們會知道其中有一個服務提供商,我們就先來完成它。
這裡只需要新建一個類,並新增相應的註釋就可以了
@Configuration
@EnableAuthorizationServer
public class MyAuthorizationServerConfig {
}
隨後我們啟動專案,就會發現控制檯有如下的語句列印:
這就表明Authorization Server已經建立起來了。 我們可根據OAuth的規則來訪問相應的介面。
第三方應用 User authenticates
在有了服務提供商之後,我們就可以根據OAuth的規則,來要求使用者給予授權。 這裡我們以code模式為例。
所以這裡需要第三方應用去呼叫介面
這裡對介面引數做一個簡單的介紹。
- localhost:8080這裡是我服務的地址以及埠,根據每個人的情況是不同的
- /oauth/authorize這個是Spring Security OAuth2預設提供的介面
- response_type:表示授權型別,必選項,此處的值固定為”code”
- client_id:表示客戶端的ID,必選項。這裡使用的是專案啟動時,控制檯輸出的security.oauth2.client.clientId,當然該值可以在配置檔案中自定義
- redirect_uri:表示重定向URI,可選項。即使用者授權成功後,會跳轉的地方,通常是第三方應用自己的地址
- scope:表示申請的許可權範圍,可選項。這一項用於服務提供商區分提供哪些服務資料
- state:表示客戶端的當前狀態,可以指定任意值,認證伺服器會原封不動地返回這個值。這裡沒有使用到該值
這裡我們訪問到介面後,會出現如下的介面
該介面主要是用於使用者登入的,不然怎麼知道想要哪個使用者的資料呢?
在登入成功後,來到如下介面
這裡就是要求使用者授權的介面了,有點類似於我們使用QQ進行第三方登入時候的介面。上面寫有了是哪一個第三方應用需要哪些資料。
我們這裡就點確認授權,這裡就會根據配置的redirect_uri
進行跳轉,並且是帶有一個引數的。
這裡我們跳轉到了:https://www.baidu.com/?code=XKxYIx。
這個code就是下一步第三方應用向伺服器申請令牌使用的
請求Token
這裡我們拿著上一步獲取到的code,以及專案初始化時列印的clientId和secret去獲取Token。
這裡需要使用POST方法,
POST /oauth/token HTTP/1.1
Host: localhost:8082
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA
&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb
請求的Header中有一個Authorization引數,該引數的值是Basic + (clientId:secret Base64值)
- grant_type:表示使用的授權模式,必選項,此處的值固定為”authorization_code”。
- code:表示上一步獲得的授權碼,必選項。
- redirect_uri:表示重定向URI,必選項,且必須與A步驟中的該引數值保持一致。
- client_id:表示客戶端ID,必選項。
如果請求成功,就可以順利的拿到Token
獲取到Token
請求Token成功後,認證伺服器傳送的HTTP回覆
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token":"2YotnFZFEjr1zCsicMWpAA",
"token_type":"example",
"expires_in":3600,
"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
"example_parameter":"example_value"
}
- access_token:表示訪問令牌,必選項。
- token_type:表示令牌型別,該值大小寫不敏感,必選項,可以是bearer型別或mac型別。
- expires_in:表示過期時間,單位為秒。如果省略該引數,必須其他方式設定過期時間。
- refresh_token:表示更新令牌,用來獲取下一次的訪問令牌,可選項。
- scope:表示許可權範圍,如果與客戶端申請的範圍一致,此項可省略。
資源伺服器
和認證伺服器一樣,這裡實現資源伺服器就很容易了
@Configuration
@EnableResourceServer
public class MyResourceServerConfig {
}
這樣我們就可以用Token來訪問介面了。
例如:
GET /user HTTP/1.1
Host: localhost:8082
Authorization: bearer 9b2aaea4-d161-4636-8883-6756a372e735
這裡Authorization中,bearer 是上一步返回的token_type。
遺留問題
目前基本功能是實現了,但是還有兩個遺留問題需要解決:
1. 現在的Token是存在Session中的,伺服器重啟後原來客戶端的Token就失效了。
2. Token現在是自動生成的,是否可以用JWT來自定義生成呢?