(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

 

posted @ 2018-11-01 17:39  nfcm  阅读(5929)  评论(0编辑  收藏  举报