shiro框架多realm权限认证配置

我们做shiro框架经常会遇到这种情况,用户数量很多,又不在同一个表里,比如管理员一个表,用户一个表,商家一个表。这时我们就需要用到多realm来配置让他们用不同得realm来进行权限认证 跟登录认证一样,首先我们来说思路,因为权限认证的话肯定已经登录过了,那么我们就可以通过principals.getPrimaryPrincipal() 获取当前登录的用户信息,然后对其进行判断看看他是哪个用户Bean的实体类以此来判断当前用哪个realm来认证

首先我们要写一个用于选择用哪个realm来认证的MyAuthorizer类继承ModularRealmAuthorizer类

java 复制代码
/*
MyAuthorizer类继承后重写其中的isPermitted(PrincipalCollection principals, String permission),
isPermitted(PrincipalCollection principals, Permission permission),
hasRole(PrincipalCollection principals, String roleIdentifier)
三个方法,其中isPermitted方法是用来验证权限,hasRole方法是用来验证角色的
 */
public class MyAuthorizer extends ModularRealmAuthorizer {
    /**
     * Returns <code>true</code> if any of the configured realms'
     * {@link #isPermitted(PrincipalCollection, String)} returns <code>true</code>,
     * <code>false</code> otherwise.
     *
     * @param principals
     * @param permission
     */
    @Override
    public boolean isPermitted(PrincipalCollection principals, String permission) {
        return super.isPermitted(principals, permission);
    }
    /**
     * Returns <code>true</code> if any of the configured realms'
     * {@link #isPermitted(PrincipalCollection, Permission)} call returns <code>true</code>,
     * <code>false</code> otherwise.
     *
     * @param principals
     * @param permission
     */
    @Override
    public boolean isPermitted(PrincipalCollection principals, Permission permission) {
        return super.isPermitted(principals, permission);
    }
    /**
     * Returns <code>true</code> if any of the configured realms'
     * {@link #hasRole(PrincipalCollection, String)} call returns <code>true</code>,
     * <code>false</code> otherwise.
     *
     * @param principals
     * @param roleIdentifier
     */
    @Override
    public boolean hasRole(PrincipalCollection principals, String roleIdentifier) {
        return super.hasRole(principals, roleIdentifier);
    }
}

三个方法里得内容基本差不多,所以这里只提供hasRole方法的写法

java 复制代码
 public boolean hasRole(PrincipalCollection principals, String roleIdentifier) {
        //判断realm是否存在
        assertRealmsConfigured();
        //获取当前登录对象实例
        Object primaryPrincipal = principals.getPrimaryPrincipal();
        //getRealms()获取当前所有的Realm,遍历所有的realm
        Iterator iterator=getRealms().iterator();
        while (iterator.hasNext()){
            Realm realm=(Realm) iterator.next();
            //判断是否是一个realm
            if (!(realm instanceof Authorizer)) continue;
            //判断当前登录对象实例是否为管理员实例
            if (primaryPrincipal instanceof Administrators) {
                if (realm instanceof AdminRealm)
                    return ((AdminRealm) realm).hasRole(principals, roleIdentifier);
            }
            //判断当前登录对象实例是否为用户实例
            if (primaryPrincipal instanceof User) {
                if (realm instanceof UserRealm)
                    return ((UserRealm) realm).hasRole(principals, roleIdentifier);
            }
            //判断当前登录对象实例是否为商户实例
            if (primaryPrincipal instanceof Merchants) {
                if (realm instanceof MerchantsRealm)
                    return ((MerchantsRealm) realm).hasRole(principals, roleIdentifier);
            }
        }
        return false;
    }

至于isPermitted方法就是把其中的return ((UserRealm) realm).hasRole(principals, roleIdentifier); 换为return ((UserRealm) realm).isPermitted(principals, permission);

然后还是一样将这个东西放到shiro配置文件里,告诉shiro用这个东西来决定用哪个realm来验证权限

java 复制代码
     @Bean
     public org.apache.shiro.mgt.SecurityManager securityManager(){
        DefaultWebSecurityManager defaultSecurityManager=new DefaultWebSecurityManager();
        defaultSecurityManager.setAuthenticator(customizedModularRealmAuthenticator());
        //将三个realm放置shiro装配到shiro框架中
        List<Realm> realms=new ArrayList<>();
        realms.add(userRealm());
        realms.add(adminRealm());
        realms.add(merchantsRealm());
        defaultSecurityManager.setRealms(realms);
        //多realm授权配置
        CustomerAuthrizer customerAuthrizer=new CustomerAuthrizer();
        customerAuthrizer.setRealms(realms);
        defaultSecurityManager.setAuthorizer(customerAuthrizer);
        return defaultSecurityManager;
    }
    @Bean
    public AdminRealm adminRealm(){
        AdminRealm adminRealm=new AdminRealm();
        //将密码加密与验证装配到realm中
        adminRealm.setCredentialsMatcher(credentialsMatcher());
        return adminRealm;
    }
    @Bean
    public UserRealm userRealm(){
        UserRealm userRealm=new UserRealm ();
        //将密码加密与验证装配到realm中
        userRealm.setCredentialsMatcher(credentialsMatcher());
        return userRealm;
    }
    @Bean
    public MerchantsRealm merchantsRealm(){
        MerchantsRealm merchantsRealm=new MerchantsRealm();
        //将密码加密与验证装配到realm中
        merchantsRealm.setCredentialsMatcher(credentialsMatcher());
        return merchantsRealm;
    }

至此多realm权限认证配置完成,realm内部以及配置文件相关在以往的文章中有详细说明

有关realm登录认证请查看:shiro框架多realm登录认证配置

相关推荐
编程、小哥哥14 分钟前
Java面试实战:从Spring Boot到分布式缓存的深度探索
java·spring boot·redis·微服务·grpc·缓存技术·面试技巧
键盘客2 小时前
Spring Boot 配置明文密码加密,防泄漏
java·spring boot·后端·spring
二进制小甜豆2 小时前
SpringBoot快速上手
java·spring boot·maven
苹果酱05672 小时前
Golang中的runtime.LockOSThread 和 runtime.UnlockOSThread
java·vue.js·spring boot·mysql·课程设计
Uranus^4 小时前
Spring Boot与Kafka集成实践:从入门到实战
spring boot·kafka·消息队列·分布式系统
Uranus^7 小时前
深入解析Java微服务架构:Spring Boot与Spring Cloud的整合实践
java·spring boot·spring cloud·微服务·分布式系统
CodeLinghu7 小时前
宝塔面板部署前后端项目SpringBoot+Vue2
java·spring boot·后端
悟能不能悟7 小时前
Spring Boot循环依赖的陷阱与解决方案:如何打破“Bean创建死循环”?
java·spring boot·spring
嘵奇9 小时前
Spring Boot中Redis序列化配置详解
spring boot·redis·后端
薯条不要番茄酱13 小时前
【SpringBoot】从零开始全面解析SpringMVC (三)
java·spring boot·后端