1. 程式人生 > >(4)shiro多個realm

(4)shiro多個realm

shiro支援多個realm,當設定多個realm的時候,shiro的認證和授權的步驟是怎樣的呢。

多個realm認證原理:

 

發現需要在執行認證的時候,需要策略來處理多個realm存在的情況。預設實現類有三個策略:

1. AtLeastOneSuccessfulStrategy :如果一個(或更多)Realm 驗證成功,則整體的嘗試被認為是成功的。如果沒有一個驗證成功,則整體嘗試失敗。

2. FirstSuccessfulStrategy 只有第一個成功地驗證的Realm 返回的資訊將被使用。後面的realm會被忽略,如果一個都沒有成功則失敗。

3. AllSucessfulStrategy 為了整體的嘗試成功,所有配置的Realm 必須驗證成功。如果沒有一個驗證成功,則整體嘗試失敗。

ModularRealmAuthenticator 預設的是AtLeastOneSuccessfulStrategy 

 

多個realm授權原理:

當shiro判斷是否有對應的角色或者資源的時候,最底層是呼叫Authenticator的doAuthenticate方法。

下面是Authenticator的一個實現類(ModularRealmAuthenticator)當有多個realms的時候執行的步驟:

得到總結:只要有一個realm裡面有這個角色或者資源就代表有這個許可權

 

程式碼測試

 1,新增一個realm2,無論如何都是通過的,返回的principal固定為test(自己可以根據業務需要,為當前登入的使用者設定別的身份)

public class MyRealm2 extends AuthorizingRealm {

    //認證資訊,
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;

        String password = new
String(upToken.getPassword()); //模擬使用者名稱密碼是否正確 return new SimpleAuthenticationInfo("test",password,getName()); } //授權 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { //獲取使用者名稱 String username = (String)getAvailablePrincipal(principals); //模擬從資料庫查詢出來對應的角色和許可權 Set<String> roles = new HashSet<String>(); roles.add("role_3"); roles.add("role_4"); Set<String> permissions = new HashSet<String>(); permissions.add("user:update"); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); info.setRoles(roles); info.setStringPermissions(permissions); return info; }

 

2配置檔案

myrealm=com.nfcm.shiro.Realm.MyRealm
myrealm2=com.nfcm.shiro.Realm.MyRealm2
#設定策略,必須所有的realm都通過
authcStrategy=org.apache.shiro.authc.pam.AllSuccessfulStrategy
#配置認證器
authenticator=org.apache.shiro.authc.pam.ModularRealmAuthenticator
#將驗證器和策略關聯起來
authenticator.authenticationStrategy=$authcStrategy
#注入認證器
securityManager.authenticator=$authenticator
#設定realm,這個要最後設定,如果後設置認證器或者授權器,則裡面的realms都是空的
securityManager.realms=$myrealm,$myrealm2

 

3.測試程式碼

        ShiroUtils.login("classpath:shiro-myrealm2.ini","zhang","123456");

        Subject subject = SecurityUtils.getSubject();

        List<String> principals =subject.getPrincipals().asList();
        for (String principal:principals) {
            System.out.println(principal);
        }

        System.out.println(subject.getPrincipals().getPrimaryPrincipal());
        //是否通過認證
        System.out.println(subject.isAuthenticated());
        //是否有role1角色
        System.out.println(subject.hasRole("role_1"));
        //realm2裡面的角色
        System.out.println(subject.hasRole("role_3"));

        System.out.println(subject.isPermitted("user:create"));
        //realm2裡面的資源
        System.out.println(subject.isPermitted("user:update"));

 

最後輸出結果:

zhang
test
zhang
true
true
true
true
true

getPrimaryPrincipal方法獲取的是第一個realm裡面的身份。

subject.getPrincipals().fromRealm("myrealm2")可以獲取指定的realm裡面的身份資訊,返回的是一個集合,獲取第一個即可。

 

github程式碼地址

https://github.com/cmniefei/shiroparent