Shiro -- (五) 授權

来源:https://www.cnblogs.com/crazy-lc/archive/2020/02/28/12380040.html
-Advertisement-
Play Games

授權 授權,也叫訪問控制,即在應用中控制誰能訪問哪些資源(如訪問頁面/編輯數據/頁面操作等)。在授權中需瞭解的幾個關鍵對象:主體(Subject)、資源(Resource)、許可權(Permission)、角色(Role)。 主體 主體,即訪問應用的用戶,在 Shiro 中使用 Subject 代表該 ...


授權

  授權,也叫訪問控制,即在應用中控制誰能訪問哪些資源(如訪問頁面/編輯數據/頁面操作等)。在授權中需瞭解的幾個關鍵對象:主體(Subject)、資源(Resource)、許可權(Permission)、角色(Role)。

主體
  主體,即訪問應用的用戶,在 Shiro 中使用 Subject 代表該用戶。用戶只有授權後才允許訪問相應的資源。

資源
  在應用中用戶可以訪問的任何東西,比如訪問 JSP 頁面、查看/編輯某些數據、訪問某個業務方法、列印文本等等都是資源。用戶只要授權後才能訪問。

許可權
  安全策略中的原子授權單位,通過許可權我們可以表示在應用中用戶有沒有操作某個資源的權力。即許可權表示在應用中用戶能不能訪問某個資源,如: 訪問用戶列表頁面
查看/新增/修改/刪除用戶數據(即很多時候都是 CRUD(增查改刪)式許可權控制)
列印文檔等等。。。

  如上可以看出,許可權代表了用戶有沒有操作某個資源的權利,即反映在某個資源上的操作允不允許,不反映誰去執行這個操作。所以後續還需要把許可權賦予給用戶,即定義哪個用戶允許在某個資源上做什麼操作(許可權),Shiro 不會去做這件事情,而是由實現人員提供。

  Shiro 支持粗粒度許可權(如用戶模塊的所有許可權)和細粒度許可權(操作某個用戶的許可權,即實例級別的),後續部分介紹。

角色
  角色代表了操作集合,可以理解為許可權的集合,一般情況下我們會賦予用戶角色而不是許可權,即這樣用戶可以擁有一組許可權,賦予許可權時比較方便。典型的如:項目經理、技術總監、CTO、開發工程師等都是角色,不同的角色擁有一組不同的許可權。

隱式角色
  即直接通過角色來驗證用戶有沒有操作許可權,如在應用中 CTO、技術總監、開發工程師可以使用印表機,假設某天不允許開發工程師使用印表機,此時需要從應用中刪除相應代碼;再如在應用中 CTO、技術總監可以查看用戶、查看許可權;突然有一天不允許技術總監查看用戶、查看許可權了,需要在相關代碼中把技術總監角色從判斷邏輯中刪除掉;即粒度是以角色為單位進行訪問控制的,粒度較粗;如果進行修改可能造成多處代碼修改。

顯示角色
  在程式中通過許可權控制誰能訪問某個資源,角色聚合一組許可權集合;這樣假設哪個角色不能訪問某個資源,只需要從角色代表的許可權集合中移除即可;無須修改多處代碼;即粒度是以資源/實例為單位的;粒度較細。

基於角色與基於資源的許可權訪問控制(RBAC和RBAC新解)

  基於角色的許可權訪問控制RBACrole-based access control)是以角色為中心進行的訪問控制,也就是判斷主體subject是那個角色的方式進行許可權訪問控制,是粗粒度的

  基於資源的許可權訪問控制RBACresource-based access control)是以資源為中心進行的訪問控制,只需要為角色添加許可權就可以

 區別:

    由於基於角色的許可權訪問控制的角色與許可權往往是多對多的關係(比如admin角色可以所有CURD的許可權,部門經理角色有Retrieve許可權,這就是多對多關係了),如果角色所對應的許可權發生變化 ,那我們所編寫的判斷邏輯就必鬚髮生改變,可擴展性差

 比如:原本只有admin可以訪問,那麼判斷可以這麼寫

      if(role.equals(”admin”)){
        //retrieve
      }

  但是假設後期需要給部門經理角色也賦予retrieve許可權,那麼必須改變原有代碼,或者另外增加代碼,總之要改變原有的判斷邏輯

  if(role.equals("admin") || role.equals("manager")){
      //retrieve    

      }

    如果是基於資源的許可權訪問控制,資源和許可權一對一關係比較常見,很多時候資源和許可權在資料庫中會被合併在一張表中,只需要為資源分配相應的許可權。所以一個具體操作對應的許可權,只要直接判斷用戶是否擁有該許可權即可,可擴展性強

   //判斷用戶是否具有查看許可權,用戶的角色可以任意變化,而這條判斷語句始終是可行的
      if(user.hasPermission("retrieve")){

        //retrieve 

      }
  如果用戶的許可權需要改變,只需要對資料庫中用戶的角色對應的許可權進行改變,而許可權與對應資源通常不會有改變的需求

 

授權方式:

Shiro 支持三種方式的授權:

編程式:通過寫 if/else 授權代碼塊完成:

Subject subject = SecurityUtils.getSubject();
if(subject.hasRole(“admin”)) {
    //有許可權
} else {
    //無許可權
}
註解式:通過在執行的 Java 方法上放置相應的註解完成:
@RequiresRoles("admin")
public void hello() {
    //有許可權
}

沒有許可權將拋出相應的異常;

JSP/GSP 標簽:在 JSP/GSP 頁面通過相應的標簽完成:

<shiro:hasRole name="admin">
<!— 有許可權 —>
</shiro:hasRole>

 

Demo:

基於角色的訪問控制(隱式角色)

配置文件:

 

 

 測試:

public class TestRole {
    @Test
    public void t1(){
        Factory<SecurityManager> factory= new IniSecurityManagerFactory("classpath:shiro-role.ini");
        SecurityManager securityManager = factory.getInstance();
        SecurityUtils.setSecurityManager(securityManager);
        Subject subject = SecurityUtils.getSubject();

        UsernamePasswordToken token=new UsernamePasswordToken("lc","123");
        try {
            subject.login(token);
            System.out.println("用戶是否擁有此角色:"+subject.hasRole("user"));
            System.out.println("用戶是否擁有任意一個角色:"+subject.hasAllRoles(Arrays.asList("admin","root")));
            System.out.println("用戶受否擁有角色:"+Arrays.toString(subject.hasRoles(Arrays.asList("admin","root"))));
           
       subject.checkRole(
"admin"); subject.checkRoles("admin","r"); System.out.println(); }catch (AuthenticationException e){ System.out.println("失敗! "+e); } subject.logout(); } }

由配置文件知,lc用戶只有admin與root兩個角色,沒有user角色,所以是false,其他兩個方法類似;checkRole檢查斷言角色,admin可以,沒有r角色所以報錯。

 

 

 

 基於資源的訪問控制(顯示角色)

  配置文件:兩個用戶對應著自己的角色,角色對應著許可權

root角色許可權:select,update,insert,delete

admin角色許可權:select,delete

user角色許可權:select

 

 

 測試:

  由配置文件知cc用戶角色為user,對應的許可權為select,lc用戶角色為root,admin,許可權為select,update,insert,delete

@Test
    public void t2(){
        Factory<SecurityManager> factory=new IniSecurityManagerFactory("classpath:shiro-permission.ini");
        SecurityManager securityManager = factory.getInstance();
        SecurityUtils.setSecurityManager(securityManager);
        Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token
=new UsernamePasswordToken("cc","123"); UsernamePasswordToken token2=new UsernamePasswordToken("lc","123"); try { subject.login(token); System.out.println(subject.isPermitted("select")); System.out.println( subject.isPermittedAll("select","insert","delete")); subject.login(token2); System.out.println(subject.isPermitted("select")); System.out.println( subject.isPermittedAll("select","insert","delete"));
        
        subject.checkPermission("select");
      subject.checkPermissions("select","insert");
}catch (AuthenticationException e){ System.out.println("nono"+e); } subject.logout(); }

結果:

 

 

 

 

授權流程

  

 

 

 

  1. 首先調用 Subject.isPermitted*/hasRole*介面,其會委托給 SecurityManager,而 SecurityManager 接著會委托給 Authorizer;
  2. Authorizer 是真正的授權者,如果我們調用如 isPermitted(“select”),其首先會通過 PermissionResolver 把字元串轉換成相應的 Permission 實例;
  3. 在進行授權之前,其會調用相應的 Realm 獲取 Subject 相應的角色/許可權用於匹配傳入的角色/許可權;
  4. Authorizer 會判斷 Realm 的角色/許可權是否和傳入的匹配,如果有多個 Realm,會委托給 ModularRealmAuthorizer 進行迴圈判斷,如果匹配如 isPermitted*/hasRole* 會返回 true,否則返回 false 表示授權失敗。

 

 

 


經典許可權系:

大致用到5張表:用戶表(UserInfo)、角色表(RoleInfo)、菜單表(MenuInfo)、用戶角色表(UserRole)、角色菜單表(RoleMenu)。

  各表的大體表結構如下:

  1、用戶表(UserInfo):Id、UserName、UserPwd

  2、角色表(RoleInfo):Id、RoleName

  3、菜單表(MenuInfo):Id、MenuName

  4、用戶角色表(UserRole):Id、UserId、RoleId

  5、角色菜單表(RoleMenu):Id、RoleId、MenuId

 

  最關鍵的地方是,某個用戶登錄時,如何查找該用戶的菜單許可權?其實一條語句即可搞定:

  假如用戶的用戶名為zhangsan,則他的菜單許可權查詢如下:

  

Select m.Id,m.MenuName from MenuInfo m ,UserInfo u UserRole ur, RoleMenu rm Where m.Id = rm.MenuId and ur.RoleId = rm.RoleId and ur.UserId = u.Id and u.UserName = 'zhangsan'

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 概述 對異常的理解 程式在運行過程中出現不正常情況。是對問題的描述,將問題進行對象的封裝。 異常的由來 問題也是現實生活中一個具體的事物,也可以通過Java的類的形式進行描述,並封裝成對象。 對於問題的劃分 一種是嚴重的問題,一種是非嚴重的問題。 + 對於嚴重的:Java通過Error類進行描述。 ...
  • [TOC] 這裡對 C 語言的指針進行比較詳細的整理總結,參考網路上部分資料整理如下。 指針概念 電腦中所有的數據都必須放在記憶體中,不同類型的數據占用的位元組數不一樣,例如 int 占用4個位元組,char 占用1個位元組。為了正確地訪問這些數據,必須為每個位元組都編上號碼,就像門牌號、身份證號一樣,每個 ...
  • 在pandas中怎麼樣實現類似mysql查找語句的功能: pandas中獲取數據的有以下幾種方法: 布爾索引 位置索引 標簽索引 使用API 假設數據如下: 布爾索引 該方法其實就是找出每一行中符合條件的真值(true value),如找出列A中所有值等於foo 位置索引 使用iloc方法,根據索引 ...
  • this是指當前對象 this.widget是指當前組件 比如我有一個 的組件ShapeStep,在_ShapeStepState中的this.widget才能訪問到str屬性,而this訪問不到。 ...
  • package com.cnblogs.test; import java.util.List; import java.util.Map; import com.google.common.collect.ImmutableMap; import com.google.common.collect ...
  • go 語言中文網(每日資訊)\_2020 02 28 一、Go 語言中文網 1. "Gopher 學習效率低怎麼辦?曹大談工程師應該怎麼學習 " 2. "Go 的 http 包中預設路由匹配規則" 3. "【每日一庫】Web 表單驗證利器:go playground/validator" 4. "從 ...
  • 此教程已支持最新2019.3版本 本教程適用Windows、Mac、Ubuntu等所有平臺。 激活前準備工作 配置文件修改已經不在bin目錄下直接修改,而是通過Idea修改 如果輸入code一直彈出來,請去hosts里移除jetbrains相關的項目 激活出現問題自己無法解決可在關註公眾號回覆 :i ...
  • 個人簡介 ​ Java後臺開發方向。 非電腦專業碩士,專業涉及到一些開發。 實驗室項目主要是Java Web系統,挖掘小亮點。 無實習經驗。 閑話嘮嗑 ​ 回顧這幾個月,宛若夢一場。 一開始心態不好,看到要學習的東西一大堆,沉不下心來學習,看什麼東西都是看著看著就很浮躁,開始瘋狂抖腿,沉迷幻想,以 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...