1. 程式人生 > >(2)shiro角色資源許可權

(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)

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。

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

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

github地址