(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

 


免責聲明!

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



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