Spring Cloud微服務安全實戰_6-4_權限控制改造


上一篇說了認證,通過令牌可以知道當前用戶是誰,並把令牌信息從網關到微服務,以及微服務與微服務之間傳遞用戶上下文的信息,這一篇來聊一下授權。

一、最簡單的情況ACL權限控制

用戶有哪些權限直接在scope里寫着,只要在程序里判斷一下要訪問某個方法,是否有訪問權限就可以了這種適用於權限簡單的場景。

使用 @PreAuthorize("") 注解標記在Controller方法,可以控制,哪些請求有權限訪問該服務。注意要想是該注解生效需要在啟動類上加上注解: @EnableGlobalMethodSecurity(prePostEnabled = true)  使其生效。

value值有兩種表達式:

  1,@PreAuthorize("#oauth2.hasScope('fly')")  表示,scope包含“fly”的令牌,才可以訪問該服務。這個針對客戶端應用的,不能具體到某一個人。

  2,@PreAuthorize("hasRole('ROLE_USER')")  具體到每一個人,這個人包含哪些角色,就能訪問,這個角色在認證服務器的 UserDetailsService  類的 loadUserByUsername 方法里獲取。

 

實驗@PreAuthorize("#oauth2.hasScope('fly')")   :

  用orderService 客戶端通過網關 ,獲取token

  

 

 

   

 

   這個token的scope只包含 read,write ,但是創建訂單服務需要token的scope包含fly才能訪問,用這個token通過網關訪問創建訂單服務:

  

 

 

 將創建訂單服務的權限控制表達式換成   @PreAuthorize("#oauth2.hasScope('write')")  就可以正常訪問。

 

實驗@PreAuthorize("#hasRole('ROLE_USER')")   :

 

 通過網關獲取令牌 

  

 

 

   創建訂單服務,有ROLE_USER角色,才能訪問

  

 

   認證服務器的UserDetailsService ,寫死的權限,只有ROLE_ADMIN

  

 

 

  通過網關拿token 創建訂單

     

 

   權限控制注解換為  @PreAuthorize("hasRole('ROLE_ADMIN')") ,則可正常調用創建訂單服務。

使用@PreAuthorize 注解處理簡單角色很方便,但是沒辦法處理復雜的場景。如果權限總是變化的,這個就不適合了,因為權限控制是硬編碼在Controller了,每次修改權限信息,還得重啟服務。

二、在網關上做復雜的權限控制

假設已經有了一個權限系統,怎么跟網關接起來?

1,在 GatewaySecurityConfig 配置類上,需要做如下的修改 

      a)  指定權限訪問規則

  在 GatewaySecurityConfig.configure(HttpSecurity http) 方法里,配置 http.access("#permissionService.hasPermission(request,authorization)")  ,指定權限訪問規則,permissionService需要自己實現,返回布爾值,true-能訪問;false-無權限,傳進去2個參數,參數1-當前請求 ,參數2-當前用戶。

 

 b) 新建 PermissionService 接口以及實現類 ,實現自己的權限控制邏輯。

 c) 新建表達式處理 GatewayWebSecurityExpressionHandler

  只指定這個權限訪問規則http.access("#permissionService.hasPermission(request,authorization)")是沒用的,因為Spring不認識,所以還得新建一個類:GatewayWebSecurityExpressionHandler (表達式處理器),用來往權限表達式處理器里設置變量,變量名就是 permissionService,變量值是
  自定義的權限處理類
PermissionService
 d)指定表達式處理器
 
    GatewaySecurityConfig.configure(ResourceServerSecurityConfigurer resources)里 指定 resources.expressionHandler(gatewayWebSecurityExpressionHandler)表達式處理器

 

 
        

 

 

 

 
        

 

 

 

 通過網關申請令牌,通過網關訪問創建訂單服務,有一半的可能性訪問失敗,一半可能性成功。

 到目前為止的項目框架結構是這樣的:

 

 

 應該是有一個權限服務的,權限服務也是一個微服務,認證服務+權限服務=安全中心。

 目前的權限都在網關控制的,這樣可能存在越權:

  比如你有權限訪問訂單服務,沒權限訪問庫存服務,但是訂單服務又調用了庫存服務,這樣就越權了。

怎么解決這個越權呢:

  a)  可以在每個微服務上,都調用redis檢查權限,做法和上邊演示的在網關上的做法是一樣的,但是不建議這么做,所有微服務都依賴redis是大量的耦合。

  b)  95%的細粒度的權限都在網關上做,微服務之期間互相調用的權限,只做一個粗粒度的黑白名單的控制,比如你一個結算服務,有一個白名單,只允許訂單服務來調用,其他人調不了。(后面介紹sentinel怎么方便的進行黑白名單的控制)。微服務之間的調用不用像網關那么做細粒度的控制,(這個服務你能不能調,那個服務你能不能調),但是要有一個黑白名單的控制就可以了,控制住那些微服務之間能調用就可以了。

 

代碼 :https://github.com/lhy1234/springcloud-security/tree/chapt-6-3-permission 如果幫到了你給個小星星吧

 

 

歡迎關注個人公眾號一起交流學習:

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM