(2)shiro角色資源權限


一般在web系統權限設計中,一般分為三個維度,用戶,角色,資源,一個用戶可以擁有多個角色,比如說可以是老師,也可以是班主任,一個角色也可以擁有多個資源。

比如老師同時擁有查看班級學生和批改作業的資源,如果一個用戶有老師這個角色,那么就代表他擁有了查看班級學生和批改作業的兩個資源權限。

因為只判斷角色顆粒度太粗,而根據資源權限則比較細。

 

校驗權限代碼

在classpath下新建shiro-role.ini文件,內容如下:

代表有一個zhang的用戶,擁有role1角色(如果有多個角色,后面用逗號繼續隔開role1,role2)

role1這個角色有兩個資源,分別是user:create和user:update。

[users]
zhang=123456,role1
[roles]
role1=user:create,user:update

測試代碼:

        Factory<SecurityManager> factory =new IniSecurityManagerFactory("classpath:shiro-role.ini");
        //得到安全管理器
        SecurityManager securityManager = factory.getInstance();
        //將securityManager托管給SecurityUtils
        SecurityUtils.setSecurityManager(securityManager);

        Subject subject = SecurityUtils.getSubject();

        UsernamePasswordToken token = new UsernamePasswordToken("zhang", "123456");

        try {
            subject.login(token);
        } catch (AuthenticationException e) {
            e.printStackTrace();
        }
        //是否已經認證
        System.out.println(subject.isAuthenticated());

        //校驗是否有對應的權限和資源,如果沒有則拋出對應的異常UnauthorizedException
        subject.checkRole("role1");
        subject.checkPermission("user:create");
        //退出
        subject.logout();

過程沒有遇到任何錯誤,執行到了最后,但是如果你check一個zhang不存在的role或者permission,則會報UnauthorizedException。

 

身份和憑證

在登陸中,用戶需要提供principals(身份)和credentials(證明/憑證)提供給shiro來進行認證和授權。

principals可以有多個身份,但是只能有一個Primary principals,一般是登錄賬號,比如手機號。

credentials一般是密碼。

在UsernamePasswordToken的賬戶密碼就對應着身份和憑證。

 

 

subject.login()原理

當執行subject.login的時候,實際調用的是securityManager所屬的Authenticator(默認是ModularRealmAuthenticator)的doAuthenticate方法進行驗證。

 

 他會根據當前設置了幾個realm走不同的方法(后面介紹多個realms)

 最終走的realm對應的getAuthenticationInfo方法,判斷用戶賬號密碼是否正確,如果錯誤則拋出對應的異常。正確則返回一個AuthenticationInfo對象。(這里是SimpleAuthenticationInfo)

 所以后面我們自定義realms的時候就覆蓋getAuthenticationInfo這個方法即可。

 

subject.checkRole原理

當用戶調用subject.checkRole("role1")判斷用戶是否有對應的角色的時候,底層還是走的SecurityManager所屬的Authorizer的checkRole方法。

hasRole然后又走了下面的方法

最后獲取到了所有的realms,上篇文章說了java環境下使用了IniRealm,並且注入到了Authenticator(認證器)和Authorizer(授權器)的一個成員變量中。

所以getRealms就可以直接獲取到所有的realms

因為IniRealms繼承了AuthorizingRealm,而IniRealm沒有實現hasRole方法,所以會走他的繼承類AuthorizingRealm里面的hasRole來判斷是否有權限。下面就是對應的方法。

在初始化IniRealm的時候會讀取所有用戶所屬的role和permission並封裝到成員變量中,getAuthorizationInfo方法就是返回了一個AuthorizationInfo對象里面獲取了zhang所屬role和permission。

所以我們自定義realm進行授權的時候就是覆蓋了realm的getAuthorizationInfo方法,里面封裝的role和permission都是從數據庫查詢出來的。

 

最后進行checkRole就很容易看懂了。

 

如果返回false,則Authorizer會拋出UnauthorizedException授權失敗異常。

 

github地址

https://github.com/cmniefei/shiroparent

 


免責聲明!

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



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