(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託管給SecurityUtilsSecurityUtils.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授權失敗異常。