日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

SpringBoot+Shiro学习(四):Realm授权

發布時間:2023/12/6 javascript 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SpringBoot+Shiro学习(四):Realm授权 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

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

授權流程

流程如下:

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

  • 首先檢查相應的Realm是否實現了實現了Authorizer;
  • 如果實現了Authorizer,那么接著調用其相應的isPermitted*/hasRole*接口進行匹配;
  • 如果有一個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") 復制代碼
  • 調用DelegatingSubject類的hasRole方法
  • public boolean hasRole(String roleIdentifier) {return hasPrincipals() && securityManager.hasRole(getPrincipals(), roleIdentifier);} 復制代碼
  • 調用AuthorizingSecurityManager的hasRole
  • public boolean hasRole(PrincipalCollection principals, String roleIdentifier) {return this.authorizer.hasRole(principals, roleIdentifier);} 復制代碼
  • AuthorizingSecurityManager類在創建的時候就注入了ModularRealmAuthorizer類為authorizer
  • public AuthorizingSecurityManager() {super();this.authorizer = new ModularRealmAuthorizer();} 復制代碼
  • 繼續跟進到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;} 復制代碼
  • 此處的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;} 復制代碼

    總結

    以上是生活随笔為你收集整理的SpringBoot+Shiro学习(四):Realm授权的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。