微服務API開放授權平台的設計與實現

  • 2019 年 11 月 14 日
  • 筆記

本文所介紹的項目是一個基於oath2協議的應用,實現的的功能邏輯與QQ互聯,微博開放平台類似,都是同一套認證授權流程。

項目結構簡單易懂,卻不偷工減料,在學習完本文內容後,讀者可以直接獲取文中的項目程式碼用於學習或者copy到公司的生產項目中修改後使用,真正達到學以致用的目的。

所涉及技術棧:

  • java
  • springboot 2.0.1.RELEASE
  • spring security 2.0.1.RELEASE
  • spring cloud oauth2 2.0.0.M7
  • mybatis 2.0.1

本項目包括功能有

  • 新用戶
  1. 用戶註冊自動分配角色許可權
  2. 用戶只能訪問自己所擁有的角色許可權訪問路徑
  • 開放平台
  1. 用戶可以申請獲取客戶ID和客戶密鑰
  2. 用戶可以通過客戶ID獲取授權碼
  3. 用戶可以通過客戶ID和密鑰以及授權碼獲取access token 和referrsh token和scope
  • 資源api服務(order-service/open-api-service)
  1. 可自定義配置需授權url
  2. 可自定義配置受限url的訪問scope
  3. 未授權用戶或訪問許可權不足用戶,頁面提示相資訊
  4. 用戶通過access token 來訪問對應url

項目概覽

首先來看一下項目的結構圖,了解項目的大致布局

  • .idea:idea工具生成的文件
  • docker: 存放Dockerfile文件用於構建容器鏡像
  • config: 項目中關於spring security和web的配置
  • controller:請求控制器
  • entity: 對象實體類包
  • handler:邏輯處理類包
  • mapper:存放mybatis mapper介面類
  • service: 業務邏輯處理類
  • util: 通用的工具類
  • postman:postman工具的測試用例
  • sql:項目的初始化sql語句
  • templates: 頁面模板文件

接下來正式介紹關於項目的細節,由於項目本身就已經有不少中文注釋,所以在講解的時候會收縮起一些程式碼的具體實現,如果讀者不習慣可以在這裡點在線比對閱讀或者fork到自己的項目里閱讀==> 項目程式碼

用戶是如何被攔截認證的

  1. 自定類 SecurityConfig 繼承了 WebSecurityConfigurerAdapter,說明SecurityConfig將會是一個 Http安全配置適配器
  2. 通過 @EnableWebSecurity打開了 HttpSecurity 的安全配置,則該類將生效

  1. 重寫 WebSecurityConfigurerAdapter 的 configure(HttpSecurity http) 方法
  2. 指定哪裡請求url是不需要攔截直接放行的
  3. 指定哪些請求是需要攔截校驗的

  1. 重寫 WebSecurityConfigurerAdapter 的 configure(AuthenticationManagerBuilder auth) 方法
  2. 指定處理認證的service服務類為 MyUserDetailsService
  3. 比對輸入的密碼和資料庫中的用戶密碼是否一致

  1. 自定類 MyUserDetailsService 實現了 spring security的UserDetailsService 介面
  2. 重寫 loadUserByUsername(String username) 方法, 其中username是頁面傳的屬性和值,屬性是固定的
  3. 獲取用戶許可權表對應的許可權詳情,並把內容設置到 UserDetails.Authorities屬性中
  4. 返回 UserDetails的子類 User

用戶註冊自動分配角色許可權

用戶註冊則往用戶表插入數據,同時往用戶角色表也插入一份數據。 當然也可以設計的更複雜些,比如根據來源、時間、白名單、內部推薦等設置不同的許可權,讀者可自行擴展。

用戶只能訪問自己所擁有的角色許可權訪問路徑

  1. 取出當前用戶的所有許可權
  2. 取出許可權的許可權標識欄位,並包裝成一個List 集合
  3. 保存包裝的許可權list集合到 UserDetails 對象中

  1. 取出所有許可權表中內容
  2. http.authorizeRequests()獲取當前的認證對象
  3. 把許可權表中的內容全部設置到 authorizeRequests中, antMatchers表示攔截的url, hasAnyAuthority表示可以訪問的許可權標識
  4. 因為在上圖中user已經設置了自己所擁有許可權的許可權標識,所以可以訪問被攔截的url

用戶可以申請獲取客戶ID和客戶密鑰

首先來看一下表結構,oauth_client_details 為spring cloud oath2自帶的表, user_client_secret 為我們自己創建的表

  1. 生成 OauthClientDetails 數據並保存至資料庫中
  2. 獲取當前登錄人資訊,並綁定OauthClientDetails的clientId至user_client_secret表中

用戶可以通過客戶ID獲取授權碼

具體的實現在spring-security-oauth包中的, 非本項目內的自我實現

客戶ID獲取授權碼 請求url: http://localhost:8080/oauth/authorize?response_type=code&client_id=client_92&redirect_uri=http://localhost:8080/code

  1. 因為是要獲取授權碼,response_type=code為固定值
  2. 客戶申請的客戶ID
  3. oauth_client_details 表中的 web_server_redirect_uri

用授權碼獲取access_token

具體的實現在spring-security-oauth包中的 org.springframework.security.oauth2.provider.endpoint.TokenEndpoint類,有興趣的同學可以在裡面進行debug調試

用授權碼獲取access_token 請求url: http://localhost:8080/oauth/token?grant_type=authorization_code&code=8fGtOV&client_id=client_92&client_secret=123456&redirect_uri=http://localhost:8080/code&scope=all

  1. 通過客戶ID獲取到的授權碼
  2. 客戶申請的客戶ID
  3. 客戶申請的客戶ID配套的客戶秘鑰
  4. oauth_client_details 表中的 web_server_redirect_uri
  5. oauth_client_details 表中的 scope

# 出現如下類似錯誤標識code失效,重新在獲取授權碼操作即可  {      "error": "invalid_grant",      "error_description": "Invalid authorization code: iq30f9"  }  複製程式碼

商戶id和商戶秘鑰獲取accessToken和刷新accessToken

  • grant_type: 授權類型,這裡設置為密碼模式
  • username: 用戶名
  • password: 用戶密碼
  • client_id: 申請得到的客戶Id
  • client_secret: 申請得到的客戶秘鑰
  • scope:範圍標識,取自 oauth_client_details 表中的 scope

刷新 accessToken

刷新 accessToken的 請求url: http://localhost:8080/oauth/token?grant_type=refresh_token&refresh_token=4741d043-e202-4de0-ae21-4f5c7ec5626e&client_id=client_1&client_secret=123456

資源api服務

如何自定義配置需授權url

如何自定義配置受限url的訪問scope

未授權用戶或訪問許可權不足用戶,頁面提示相應資訊

用戶通過access token 來訪問對應url

項目程式碼點這裡

Tags: