SpringBoot+Shiro學習(四):Realm授權

上一節我們講了自定義Realm中的認證(doGetAuthenticationInfo),這節我們繼續講另一個方法doGetAuthorizationInfo授權

授權流程

流程如下:

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

ModularRealmAuthorizer進行多Realm匹配流程:

  1. 首先檢查相應的Realm是否實現了實現了Authorizer;
  2. 如果實現了Authorizer,那么接著調用其相應的isPermitted*/hasRole*接口進行匹配;
  3. 如果有一個Realm匹配那么將返回true,否則返回false。

如果Realm進行授權的話,應該繼承AuthorizingRealm,其流程是:
1.1、如果調用hasRole,則直接獲取AuthorizationInfo.getRoles()與傳入的角色比較即可;
1.2、首先如果調用如isPermitted(“user:view”),首先通過PermissionResolver將權限字符串轉換成相應的Permission實例,默認使用WildcardPermissionResolver,即轉換為通配符的WildcardPermission;
2、通過AuthorizationInfo.getObjectPermissions()得到Permission實例集合;通過AuthorizationInfo. getStringPermissions()得到字符串集合并通過PermissionResolver解析為Permission實例;然后獲取用戶的角色,并通過RolePermissionResolver解析角色對應的權限集合(默認沒有實現,可以自己提供);
3、接著調用Permission. implies(Permission p)逐個與傳入的權限比較,如果有匹配的則返回true,否則false。


先看一段簡單的授權方法重寫

    @Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {//獲取用戶名String username = (String) principals.getPrimaryPrincipal();//此處從數據庫獲取該用戶的角色Set<String> roles = getRolesByUserName(username);//此處從數據庫獲取該角色的權限Set<String> permissions = getPermissionsByUserName(username);//放到info里返回SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();info.setStringPermissions(permissions);info.setRoles(roles);return info;}
復制代碼

PrincipalCollection

因為我們可以在Shiro中同時配置多個Realm,所以呢身份信息可能就有多個;因此其提供了PrincipalCollection用于聚合這些身份信息:

public?interface?PrincipalCollection?extends?Iterable,?Serializable?{??Object?getPrimaryPrincipal();?//得到主要的身份??<T>?T?oneByType(Class<T>?type);?//根據身份類型獲取第一個??<T>?Collection<T>?byType(Class<T>?type);?//根據身份類型獲取一組??List?asList();?//轉換為List??Set?asSet();?//轉換為Set??Collection?fromRealm(String?realmName);?//根據Realm名字獲取??Set<String>?getRealmNames();?//獲取所有身份驗證通過的Realm名字??boolean?isEmpty();?//判斷是否為空??
}???
復制代碼

因為PrincipalCollection聚合了多個,此處最需要注意的是getPrimaryPrincipal,如果只有一個Principal那么直接返回即可,如果有多個Principal,則返回第一個(因為內部使用Map存儲,所以可以認為是返回任意一個);oneByType / byType根據憑據的類型返回相應的Principal;fromRealm根據Realm名字(每個Principal都與一個Realm關聯)獲取相應的Principal。

AuthorizationInfo

AuthorizationInfo用于聚合授權信息的:

public?interface?AuthorizationInfo?extends?Serializable?{??Collection<String>?getRoles();?//獲取角色字符串信息??Collection<String>?getStringPermissions();?//獲取權限字符串信息??Collection<Permission>?getObjectPermissions();?//獲取Permission對象信息??
}???
復制代碼

當我們使用AuthorizingRealm時,如果身份驗證成功,在進行授權時就通過doGetAuthorizationInfo方法獲取角色/權限信息用于授權驗證。 Shiro提供了一個實現SimpleAuthorizationInfo,大多數時候使用這個即可。


我們再跟蹤一下代碼,看看是如何調用Authorizer

subject.hasRole("admin")
復制代碼
  1. 調用DelegatingSubject類的hasRole方法
    public boolean hasRole(String roleIdentifier) {return hasPrincipals() && securityManager.hasRole(getPrincipals(), roleIdentifier);}
復制代碼
  1. 調用AuthorizingSecurityManager的hasRole
 public boolean hasRole(PrincipalCollection principals, String roleIdentifier) {return this.authorizer.hasRole(principals, roleIdentifier);}
復制代碼
  1. AuthorizingSecurityManager類在創建的時候就注入了ModularRealmAuthorizer類為authorizer
    public AuthorizingSecurityManager() {super();this.authorizer = new ModularRealmAuthorizer();}
復制代碼
  1. 繼續跟進到ModularRealmAuthorizer的hasRole方法
    public boolean hasRole(PrincipalCollection principals, String roleIdentifier) {assertRealmsConfigured();for (Realm realm : getRealms()) {if (!(realm instanceof Authorizer)) continue;if (((Authorizer) realm).hasRole(principals, roleIdentifier)) {return true;}}return false;}
復制代碼
  1. 此處的hasRole是調用AuthorizingRealm抽象類的hasRole方法。同理,isPermitted也是最后調用到此。
    public boolean hasRole(PrincipalCollection principal, String roleIdentifier) {AuthorizationInfo info = getAuthorizationInfo(principal);return hasRole(roleIdentifier, info);}protected boolean hasRole(String roleIdentifier, AuthorizationInfo info) {return info != null && info.getRoles() != null && info.getRoles().contains(roleIdentifier);}public boolean isPermitted(PrincipalCollection principals, String permission) {Permission p = getPermissionResolver().resolvePermission(permission);return isPermitted(principals, p);}public boolean isPermitted(PrincipalCollection principals, Permission permission) {AuthorizationInfo info = getAuthorizationInfo(principals);return isPermitted(permission, info);}//changed visibility from private to protected for SHIRO-332protected boolean isPermitted(Permission permission, AuthorizationInfo info) {Collection<Permission> perms = getPermissions(info);if (perms != null && !perms.isEmpty()) {for (Permission perm : perms) {if (perm.implies(permission)) {return true;}}}return false;}
復制代碼

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/281281.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/281281.shtml
英文地址,請注明出處:http://en.pswp.cn/news/281281.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Git放棄文件修改

已提交 # 撤銷提交&#xff0c;保留修改內容 git reset <commit_id># 撤銷提交&#xff0c;不保留修改內容 git reset --hard <commit_id>已暫存文件 # 撤銷單個文件暫存 git reset HEAD <filename># 撤銷所有文件/文件夾暫存 git reset HEAD .已跟蹤未暫存…

[LeetCode][Java] Unique Paths II

題目&#xff1a; Follow up for "Unique Paths": Now consider if some obstacles are added to the grids. How many unique paths would there be? An obstacle and empty space is marked as 1 and 0 respectively in the grid. For example, There is one obst…

lua windows下編譯

從Lua5.1開始官方給出的文件只有源代碼和makefile文件了&#xff0c;官網給出的bulid方式也是在linux平臺&#xff0c;如果只是想找個庫使用下可以到這里來下載&#xff1a;http://joedf.ahkscript.org/LuaBuilds/ &#xff0c;如果需要自定修改庫配置的話&#xff0c;就需要自…

XAML 創建瀏覽器應用程序

XAML 創建瀏覽器應用程序XAML 創建瀏覽器應用程序作者&#xff1a;WPFDevelopersOrg - 驚鏵原文鏈接&#xff1a;https://learn.microsoft.com/zh-cn/dotnet/desktop/wpf/app-development/wpf-xaml-browser-applications-overview?viewnetframeworkdesktop-4.8框架使用.NET40&…

Git 合并分支選項 --squash 合并提交歷史

git merge --squash <branchname>--squash選項的含義是&#xff1a;本地文件內容與不使用該選項的合并結果相同&#xff0c;但是不提交、不移動HEAD&#xff0c;因此需要一條額外的commit命令。其效果相當于將another分支上的多個commit合并成一個&#xff0c;放在當前分…

Kubernetes共享使用Ceph存儲

目錄 簡要概述環境測試結果驗證簡要概述 Kubernetes pod 結合Ceph rbd塊設備的使用&#xff0c;讓Docker 數據存儲在Ceph,重啟Docker或k8s RC重新 調 度pod 不會引起數據來回遷移。 工作原理無非就是拿到ceph集群的key作為認證&#xff0c;遠程rbdmap映射掛載使用。那么就要啟用…

在Activity不可見時暫停WebView的語音播放,可見時繼續播放之前的語音

private AudioManager mAudioManager;private AudioManager.OnAudioFocusChangeListener mFocusChangeListener; Override protected void onPause() {   super.onPause();   stopPlayVoice(); } Override protected void onResume() {   super.onResume();   startPla…

MFC界面庫BCGControlBar v25.3新版亮點:Dialogs和Forms

2019獨角獸企業重金招聘Python工程師標準>>> 親愛的BCGSoft用戶&#xff0c;我們非常高興地宣布BCGControlBar Professional for MFC和BCGSuite for MFC v25.3正式發布&#xff01;新版本添加了對Visual Studio 2017的支持、增強對Windows 10的支持等。接下來幾篇文…

基于 .NET 7 的 QUIC 實現 Echo 服務

前言隨著今年6月份的 HTTP/3 協議的正式發布&#xff0c;它背后的網絡傳輸協議 QUIC&#xff0c;憑借其高效的傳輸效率和多路并發的能力&#xff0c;也大概率會取代我們熟悉的使用了幾十年的 TCP&#xff0c;成為互聯網的下一代標準傳輸協議。在去年 .NET 6 發布的時候&#xf…

php.ini-development和php.ini-production的區別

使用zip版MySQL安裝時&#xff0c;需要將php.ini-development或php.ini-production改成php.ini&#xff0c;那么php.ini-development和php.ini-production的區別在哪兒呢&#xff0c;通俗的說法時&#xff0c;development是開發環境&#xff0c;production用于生產環境&#xf…

Server.MapPath()的用法

http://blog.csdn.net/qiuhaifeng_csu/article/details/19416407 Server.MapPath(string path)作用是返回與Web服務器上的指定虛擬路徑相對應的物理文件路徑。其參數path為Web 服務器的虛擬路徑&#xff0c;返回結果是與path相對應的物理文件路徑。但有時參數并非為虛擬路徑&a…

為什么阿里巴巴禁止把SimpleDateFormat定義為static類型的?

在日常開發中&#xff0c;我們經常會用到時間&#xff0c;我們有很多辦法在Java代碼中獲取時間。但是不同的方法獲取到的時間的格式都不盡相同&#xff0c;這時候就需要一種格式化工具&#xff0c;把時間顯示成我們需要的格式。 最常用的方法就是使用SimpleDateFormat類。這是一…

關于信息收集和加工的思考

隨著互聯網的發展&#xff0c;獲取信息的手段越來越多&#xff0c;我們對手機的依賴程度超乎想象&#xff0c;每天忙碌著&#xff0c;大腦接收著豐富的信息&#xff0c;感覺每天都學習到了很多的知識。但我們對學習經常會有些誤區&#xff1a;1、書買了擺在書架上&#xff0c;看…

[譯]關于NODE_ENV,哪些你應該了解

原文 Node.js開發者經常檢測環境變量NODE_ENV&#xff0c;但你是否知道設置這個值同時也具有著某些別的意義&#xff1f;閱讀本文你將發現這些。NODE_ENV是一個在Express框架中極其常用的環境變量。用其確定應用的運行環境&#xff08;諸如開發&#xff0c;staging&#xff0c;…

GatewayWorker Not Support On Windows.

thinkphp版本&#xff1a;5.1 tp5.1運行命令行php think worker:gateway出現GatewayWorker Not Support On Windows.是因為在tp5.1的命令行中做了判定&#xff0c;不支持windows環境下運行。 這里不支持windows環境并不是說gateway worker不支持windows&#xff0c;而是tp5.1的…

8支團隊正在努力構建下一代Ethereum

“我們不想在構建 Ethereum 2.0時重新造輪子。” 談到開發人員為 Ethereum 區塊鏈進行兩個獨立的升級&#xff08;一個稱為 Ethereum 2.0&#xff0c;另一個稱為 Ethereum 1x&#xff09;所作出的補充努力&#xff0c;勞爾喬丹堅持認為&#xff0c;在較短的時間內將升級包括在 …

fastjson SerializerFeature詳解

名稱含義備注QuoteFieldNames輸出key時是否使用雙引號,默認為true UseSingleQuotes使用單引號而不是雙引號,默認為false WriteMapNullValue是否輸出值為null的字段,默認為false WriteEnumUsingToStringEnum輸出name()或者original,默認為false UseISO8601DateFormatDate使用ISO…

費曼學習法中問題的提出與反問,擴展與主動查詢的學習習慣訓練過程

在2022年11月05日的對話中&#xff0c;九遷先講了女媧補天和女媧造人的故事&#xff0c;女媧造人的故事還講了兩個版本的&#xff0c;隨后提到了一個事情&#xff0c;那就是&#xff0c;如果你要找一個神仙一起度過一天&#xff0c;你想找誰&#xff0c;想做些什么&#xff1f;…

Fiddle:使用斷點:bpu,bpafter

http://www.cnblogs.com/yoyoketang/p/6778006.html轉載于:https://www.cnblogs.com/peixianping/p/7230021.html

windows環境下TP5.1使用think-worker(Workerman/GatewayWorker)

文章目錄首先是解決如何運行gatewayworker調試gatewayworker程序向指定客戶端發送消息在TP框架中調用Gateway的API總結說明測試環境 windows10&#xff1b;PHP7.2&#xff1b;TP5.1&#xff1b; 這里只介紹如何使用TP集成的workerman擴展庫think-worker&#xff0c;原生workerm…