博客 / 詳情

返回

微服務開發系列:鑑權

源碼地址

微服務開發系列:開篇
微服務開發系列:為什麼選擇 kotlin
微服務開發系列:為什麼用 gradle 構建
微服務開發系列:目錄結構,保持整潔的文件環境
微服務開發系列:服務發現,nacos 的小補充
微服務開發系列:怎樣在框架中選擇開源工具
微服務開發系列:數據庫 orm 使用
微服務開發系列:如何打印好日誌
微服務開發系列:鑑權
微服務開發系列:認識到序列化的重要性
微服務開發系列:設計一個統一的 http 接口內容形式
微服務開發系列:利用異常特性,把異常納入框架管理之中
微服務開發系列:利用 knife4j,生成最適合微服務的文檔

在框架中,使用的鑑權模塊是 spring security

1 鑑權模塊:gateway

gateway 的模塊,涉及到 http 方面的代碼,由於是 webflux 架構 ,都與傳統的 servlet 相差甚遠,因此需要對 webflux 中使用的 reactor 響應式編程有一定的瞭解。

spring security 最主要的應用模塊是 gateway。這裏管理了所有的 http 請求,所以在一箇中型系統中是最適合鑑權的地方,同時 gateway 也是網關模塊。

所有與鑑權相關的類都在包路徑 cn.gateway.framework.security 下。

下面是對各個類的説明。

1.1 AuthenticationManager

自定義用户鑑權管理類。

用於對自定義的 cn.framework.common.security.User 擴展字段的驗證。

在此類中,校驗了 credentialsBeenReset 這個自定義擴展字段,如果為 false,提示前端用户需要進行密碼重置,否則無法繼續登錄。

1.2 LoginConverter

自定義的從 http 請求中獲取登錄信息的類。

在該類中,除了提供解析請求中的 username 和 password,還增加了對驗證碼的校驗。

是否校驗驗證碼,可以通過配置 gateway.login.verify.enable 選擇是否開啓,默認不開啓。

1.3 SecurityBeanConfig

spring security 需要用的 bean 在此類中定義。

目前只定義了兩個 bean:

  1. PasswordEncoder 密碼的加密方式
  2. ServerSecurityContextRepository,session 的保存位置

1.4 UserDetailsServiceImpl

用户信息的加載。

在這裏定義了根據 username 獲取用户信息。

因為用户信息的獲取在 business-web 模塊,開放 http 接口並不安全,所以使用了 redisson 提供的 RemoteService rpc的方式調用,獲取用户信息。

1.5 VerifyCodeController

獲取驗證的接口,調用此接口來判斷是否開啓驗證碼功能,同樣是受到 gateway.login.verify.enable  的控制,默認不開啓。

在成功獲取到驗證碼之後,會將驗證碼的代碼保存到 websession 中,同時設置 websession 的最大有效時間,也就是驗證碼的有效時間,通過配置 gateway.login.verify.timeout 控制。

最後,只需要將驗證碼轉化為 base64 返回給前台即可。

1.6 WebfluxSecurityConfig

此類是 spring security 開啓的入口類,所有與 spring security 相關的配置都在這裏完成。

上面的所有類,都是為此類服務的。

具體有如下功能。

  1. 設置 session 有效時間,通過配置 gateway.session.max-interval-seconds 控制
  2. 設置登錄配置,在方法 setLogin,包括 url 路徑,登錄成功後操作,登錄失敗後操作
  3. 設置登出配置,在方法 setLogout,包括 url 路徑,登錄成功後操作
  4. 設置權限,在方法 setPermission,給 url 設置權限驗證或者排除權限驗證,除此之外,還能夠靈活的設置權限,比如包含參數、請求方法、用户角色、用户資源清單等方面限制,如果後續有垂直鑑權的需求,也是在此處完成

2 下游系統

下游系統指的是,所有請求都要經過 gateway 的系統。

在改框架中,不對下游系統做任何權限方便的設置,但還是依賴了 spring security 體系,原因有兩個

  1. 防止以後有擴展需求,需要用到
  2. 需要不在代碼層面接收來自網關的權限信息,能夠通過框架自然完成銜接

下游系統的權限配置全部關閉,通過 framework:cn.framework.config.security.MvcSecurityHttpConfig 完成。

因為完全沒有權限驗證機制,因此下游系統必須關閉對外部的網絡連接,所有的請求都必須經過網關,否則整個系統等於沒有權限驗證。
在設計的過程中不是沒有考慮到,但在搭建的過程中進行了思考與對其它系統的參考,認為沒有開啓的必要,如果需要開啓,上面已經提到過,已經預留了開啓方式。

3 認證信息傳遞

認證信息的生成與傳遞,全部由 spring security 自動完成,沒有自定義代碼參與。

認證信息的傳遞,包含了兩種傳遞渠道

  1. 網關 -> 前台
  2. 網關 -> 下游

3.1 網關 -> 前台

一開始框架採用的方式是使用 cookie 傳遞到前台,這也是 spring security 的默認傳遞方式。

但是這樣做面臨了很多問題。

  1. 日益嚴格的安全保護,從瀏覽器到 axios 都對 cookie 進行了嚴格的限制,即使使用 csrf,也不能完全避免限制。
  2. IE 瀏覽器在跨域下對 cookie 支持有嚴重的問題,使用起來非常困難
  3. 前台需要為保留 cookie 做很多定製化的改造

因此,框架中完全拋棄 cookie 的使用,轉而使用自定義 header 的方式,參數為 X-Auth-Token

對此,spring security 已經提供了配置的方式。

網關配置在 gateway:cn.gateway.framework.session.WebfluxHttpSessionConfig 類中。

3.2 網關 -> 下游

網關在接收到包含 X-Auth-Token 的請求後,會自動將 X-Auth-Token 轉發到下游系統中。

下游系統為了能夠方便的獲取到認證信息,只需要與網關配置一樣的認證信息方式。

下游系統統一配置在 framework:cn.framework.config.session.MvcHttpSessionConfig 類中。

認證信息能夠通過 framework:cn.framework.common.security.User#currentUserForMvc 方法方便的獲取到認證信息。

如果需要擴展認證信息,比如帶上用户機構、用户郵箱等信息,只需要擴展 UserUserDeserializer 兩個類即可。

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.