OAuth2使用Redis來存儲客戶端資訊以及AccessToken

  • 2019 年 12 月 19 日
  • 筆記

使用Redis來存儲OAuth2相關的客戶端資訊以及生成的AccessToken是一個不錯的選擇,Redis與生俱來的的高效率、集群部署是比較出色的功能,如果用來作為服務認證中心的數據存儲,可以大大的提高響應效率。

Redis還支援超時自動刪除功能,OAuth2所生成的AccessToken相關的數據在超過配置的有效時間後就會自動被清除,這樣也隱形的提高了介面的安全性。

既然Redis可以做到這麼好,我們該怎麼實現程式碼邏輯呢?

ApiBoot OAuth2是支援使用Redis來存儲AccessToken的,只需要修改application.yml一個配置就可以實現,相關的使用也可以通過查看文檔了解。

ApiBoot Security OAuth組件系列文章

創建項目

我們使用IDEA開發工具創建一個SpringBoot項目,在項目的pom.xml添加我們需要的ApiBoot統一版本依賴以及安全組件依賴,如下所示:

<dependencies>    <dependency>      <groupId>org.springframework.boot</groupId>      <artifactId>spring-boot-starter-web</artifactId>    </dependency>    <dependency>      <groupId>org.minbox.framework</groupId>      <artifactId>api-boot-starter-security-oauth-jwt</artifactId>    </dependency>  </dependencies>  <dependencyManagement>    <dependencies>      <dependency>        <groupId>org.minbox.framework</groupId>        <artifactId>api-boot-dependencies</artifactId>        <version>2.2.0.RELEASE</version>        <type>pom</type>        <scope>import</scope>      </dependency>    </dependencies>  </dependencyManagement>

添加Redis支援

既然我們本章需要用到Redis,我們需要在項目內添加相關的依賴,SpringBoot已經為我們提供了封裝好的依賴,在pom.xml文件內dependencies節點下添加,如下所示:

<dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-data-redis</artifactId>  </dependency>

配置Redis連接資訊

SpringBootRedis的連接、數據操作都做了封裝,我們只需要在application.yml配置文件內添加響應的Redis連接資訊即可。

spring-boot-starter-data-redis依賴所需要的配置都是由RedisProperties類提供,該類內有部分配置欄位存在默認值,部分源碼如下所示:

@ConfigurationProperties(prefix = "spring.redis")  public class RedisProperties {        /**       * Database index used by the connection factory.       */      private int database = 0;        /**       * Connection URL. Overrides host, port, and password. User is ignored. Example:       * redis://user:[email protected]:6379       */      private String url;        /**       * Redis server host.       */      private String host = "localhost";        /**       * Login password of the redis server.       */      private String password;        /**       * Redis server port.       */      private int port = 6379;    //...  }   

默認配置下連接Redis只需要在application.yml配置spring.redis.password,如下所示:

spring:    # 配置Redis連接資訊    redis:      password: 123123

password是連接Redis所需要的密碼,在redis.conf文件內配置。

相關配置解釋:

  • spring.redis.database:如果你使用的Redis DataBase並不是默認的0索引,需要修改該配置
  • spring.redis.host:默認為localhost,如果不是本地使用,需要修改該配置
  • spring.redis.url:這是一個連接字元串,如天配置了會自動覆蓋databasehostport等三個配置資訊
  • spring.redis.port:默認為Redis的埠號6379,如已修改Redis的監聽埠號,需要修改該配置

啟用ApiBoot OAuth Redis

ApiBoot OAuth提供了redis配置選項,在application.yml文件內通過api.boot.oauth.away配置參數指定,如下所示:

api:    boot:      security:        # 配置記憶體安全用戶列表        users:          - username: yuqiyu            password: 123123      oauth:        # 配置使用Redis存儲OAuth2相關數據        away: redis        # 配置客戶端列表        clients:          - clientId: minbox            clientSecret: chapter

為了方便演示,我們使用ApiBoot Security的記憶體方式配置了一個用戶yuqiyu,而且還修改了默認client資訊,新加了minbox客戶端。

如果對ApiBoot Security用戶配置或者ApiBoot OAuth的客戶端配置不了解,可以查看官方文檔:

運行測試

在運行測試之前我們添加一個名為ApiController的控制器用來測試,程式碼如下所示:

/**   * 測試Api控制器   *   * @author 恆宇少年   */  @RestController  @RequestMapping(value = "/api")  public class ApiController {      /**       * 測試請求,需攜帶令牌訪問       *       * @return       */      @GetMapping(value = "/index")      public String index() {          return "this is index";      }  }

測試點:查看Redis存儲的AccessToken

預計效果是當我們發送獲取AccessToken的請求時,會自動將生成的AccessToken存儲到Redis

下面我們使用CURL命令來嘗試獲取下AccessToken,如下所示:

➜ ~ curl minbox:chapter@localhost:9090/oauth/token -d 'grant_type=password&username=yuqiyu&password=123123'  {"access_token":"38a7ee20-2fad-43c5-a349-31e6f0ee0f29","token_type":"bearer","refresh_token":"f469b1e8-f63c-4be9-8564-2603f8458024","expires_in":7199,"scope":"api"}

下面我們使用redis-cli來看下是否已經將AccessToken存儲到Redis,如下所示:

➜ ~ redis-cli  127.0.0.1:6379> auth 123123  OK  127.0.0.1:6379> keys *   1) "uname_to_access:minbox:yuqiyu"   2) "refresh_to_access:f469b1e8-f63c-4be9-8564-2603f8458024"   3) "access_to_refresh:1ea8e5cd-ea63-4a73-969f-9e7767f25f30"   4) "auth:38a7ee20-2fad-43c5-a349-31e6f0ee0f29"   5) "refresh_auth:6898bef4-f4a7-4fa9-858b-a4c62a1567d8"   6) "refresh:6898bef4-f4a7-4fa9-858b-a4c62a1567d8"   7) "refresh_auth:f469b1e8-f63c-4be9-8564-2603f8458024"   8) "access:38a7ee20-2fad-43c5-a349-31e6f0ee0f29"   9) "refresh_to_access:6898bef4-f4a7-4fa9-858b-a4c62a1567d8"  10) "auth_to_access:f02ceb5faa4577222082842b82a57067"  11) "refresh:f469b1e8-f63c-4be9-8564-2603f8458024"  12) "access_to_refresh:38a7ee20-2fad-43c5-a349-31e6f0ee0f29"  13) "client_id_to_access:minbox"

結果往往讓人感覺驚喜,看到這裡我們已經成功的把OAuth2生成的AccessToken存儲到了Redis,如果AccessToken對應的數據超過了expires_in時間,就會自動被清除。

測試點:攜帶AccessToken訪問介面

我們可以拿著生成的AccessToken來訪問在上面添加的測試ApiController內的介面,如下所示:

➜ ~ curl -H 'Authorization: Bearer 38a7ee20-2fad-43c5-a349-31e6f0ee0f29' http://localhost:9090/api/index  this is index

我們可以拿到介面的返回的介面,這也證明了一點,AccessToken的驗證是沒有問題的,OAuth2拿著請求攜帶的AccessTokenRedis驗證通過。

敲黑板,劃重點

ApiBoot OAuth所支援的3種存儲方式都已經通過文章的方式告知大家,每一種方式都做到了精簡,簡單的配置,添加相關的依賴,就能夠實現在之前讓很多人頭疼的集成。

如果在生產環境中數據量較大,建議使用Redis集群來解決存儲AccessToken的問題。

如果你對ApiBoot OAuth其它兩種存儲方式不了解,可以查看我編寫的ApiBoot系列的文章:ApiBoot開源框架各個組件的系列使用文章匯總

程式碼示例

如果您喜歡本篇文章請為源碼倉庫點個Star,謝謝!!! 本篇文章示例源碼可以通過以下途徑獲取,目錄為apiboot-oauth-use-redis-storage