Spring Boot(十一)Shiro 整合 配置多 Realm

import java.util.ArrayList;
import java.util.Collection;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.realm.Realm;

/**
 * CustomizedModularRealmAuthenticator
 * 多Realm验证模块
 */
public class CustomizedModularRealmAuthenticator extends ModularRealmAuthenticator {

    @Override
    protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken)
            throws AuthenticationException {
        // 判断getRealms()是否返回为空
        assertRealmsConfigured();
        // CustomizedToken
        CustomizedToken customizedToken = (CustomizedToken) authenticationToken;
        // 登录类型
        String loginType = customizedToken.getLoginType();
        // 所有Realm
        Collection<Realm> realms = getRealms();
        // 登录类型对应的所有Realm
        Collection<Realm> typeRealms = new ArrayList<>();
        for (Realm realm : realms) {
            //可以修改此规则来匹配你的登录类型
            if (realm.getName().contains(loginType)) {
                typeRealms.add(realm);
            }
        }
        if (typeRealms.size() == 1) {
            //单Realm
            return doSingleRealmAuthentication(typeRealms.iterator().next(), customizedToken);
        }
        else {
            //多Realm
            return doMultiRealmAuthentication(typeRealms, customizedToken);
        }
    }
}
import org.apache.shiro.authc.UsernamePasswordToken;

public class CustomizedToken extends UsernamePasswordToken {

    //登录类型
    private String loginType;

    public CustomizedToken(final String username, final String password,String loginType) {
        super(username,password);
        this.loginType = loginType;
    }

    public String getLoginType() {
        return loginType;
    }

    public void setLoginType(String loginType) {
        this.loginType = loginType;
    }
}
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hwx.api.entity.StoreUser;
import com.hwx.api.entity.SysUser;
import com.hwx.api.service.IMiniappConfigService;
import com.hwx.api.service.IStoreUserService;
import com.hwx.util.Const;
import com.hwx.util.Jurisdiction;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;

import javax.annotation.Resource;

public class ShiroRealmMini extends AuthorizingRealm {
    @Resource
    IStoreUserService iStoreUserService;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        return null;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //获取用户的输入的账号.
        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
        String username = usernamePasswordToken.getUsername();
        String password = String.valueOf(usernamePasswordToken.getPassword());

        //根据用户名查询,用户名必须是唯一
        QueryWrapper<StoreUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("openId", username);
        StoreUser storeUser = iStoreUserService.getOne(queryWrapper);

        /*校验密码*/
        /*加密方式*/
        String algorithmName = "MD5";
        /*加密次数*/
        int hashIterations = 2000;
        /*加密盐值 username作为颜值必须为唯一值 注册时需要注意*/
        Object salt = ByteSource.Util.bytes(storeUser.getUnionId());
        /*md5Result:9ec808d39c36c800591f1ee14f5f3175*/
        String md5Result = new SimpleHash("MD5", password, salt, hashIterations).toHex();
        /*判断用户密码是否正确,状态等*/
        if (storeUser != null) {
            if (md5Result.equals(storeUser.getPassword())) {
                /*session用户*/
                Session session = Jurisdiction.getSession();
                session.setAttribute(username + Const.SESSION_USER,storeUser);
                /*通过身份验证*/
                /*principal:认证信息,可以是username,也可以是整个实体*/
                Object principal = storeUser;
                /*credentials:密码*/
                Object credentials = storeUser.getPassword();
                /*credentialsSalt:盐值*/
                ByteSource credentialsSalt = ByteSource.Util.bytes(storeUser.getUnionId());
                /*realmName:当前realm对象的name,调用父类getName()*/
                String realmName = getName();

                SimpleAuthenticationInfo simpleAuthorizationInfo  = new SimpleAuthenticationInfo(principal, credentials, credentialsSalt, realmName);
                return simpleAuthorizationInfo;
            }
        }
        return null;
    }
}

import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;

import java.util.*;

@Configuration
public class ShiroConfig {

    @Bean
    public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
        System.out.println("ShiroConfiguration.shirFilter()");
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        /*拦截器*/
        Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>();
        /*配置不会被拦截的链接 顺序判断*/
        /*anon:所有url都都可以匿名访问*/
        /*webjars swagger 加载到webjar的资源,所以webjar下的资源不能被拦截,否者无法访问*/
        filterChainDefinitionMap.put("/webjars/**", "anon");
        filterChainDefinitionMap.put("/swagger-ui.html", "anon");
        filterChainDefinitionMap.put("/swagger-resources/**", "anon");
        filterChainDefinitionMap.put("/v2/api-docs/**", "anon");
        filterChainDefinitionMap.put("/app/**", "anon");
        filterChainDefinitionMap.put("/D://uploadfile/**", "anon");

        /*配置退出*/
        filterChainDefinitionMap.put("/logout", "logout");
        filterChainDefinitionMap.put("/api/user/login", "anon");
        filterChainDefinitionMap.put("/api/user/minilogin", "anon");
        filterChainDefinitionMap.put("/api/file/fileUpload", "anon");
        filterChainDefinitionMap.put("/index", "anon");
        /*过滤链定义,从上向下顺序执行,一般将/**放在最为下*/
        /*authc:所有url都必须认证通过才可以访问-->*/
        filterChainDefinitionMap.put("/**", "authc");
        /*如果不设置默认会自动寻找Web工程根目录下的"/login"页面*/
        shiroFilterFactoryBean.setLoginUrl("/app/admin/index.html");
        /* 登录成功后要跳转的链接*/
        shiroFilterFactoryBean.setSuccessUrl("/userInfo");
        /*未授权界面*/
        shiroFilterFactoryBean.setUnauthorizedUrl("/403");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

        return shiroFilterFactoryBean;
    }

    /**
     * 系统自带的Realm管理,主要针对多realm
     * */
    @Bean
    public ModularRealmAuthenticator modularRealmAuthenticator(){
        //自己重写的ModularRealmAuthenticator
        CustomizedModularRealmAuthenticator customizedModularRealmAuthenticator = new CustomizedModularRealmAuthenticator();
        customizedModularRealmAuthenticator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());
        return customizedModularRealmAuthenticator;
    }

    /**
     * 凭证匹配器(由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了)
     * @return
     */
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher(){
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName("md5");   //散列算法:这里使用MD5算法;
        hashedCredentialsMatcher.setHashIterations(2000);       //散列的次数,比如散列两次,相当于 md5(md5(""));
        return hashedCredentialsMatcher;
    }

    @Bean
    public ShiroRealmPC ShiroRealmPC(){
        ShiroRealmPC shiroRealmPC = new ShiroRealmPC();
        shiroRealmPC.setCredentialsMatcher(hashedCredentialsMatcher());
        return shiroRealmPC;
    }

    @Bean
    public ShiroRealmMini ShiroRealmMini(){
        ShiroRealmMini shiroRealmMini = new ShiroRealmMini();
        shiroRealmMini.setCredentialsMatcher(hashedCredentialsMatcher());//设置解密规则
        return shiroRealmMini;
    }

    @Bean
    public SecurityManager securityManager(){
        DefaultWebSecurityManager securityManager =  new DefaultWebSecurityManager();
        securityManager.setAuthenticator(modularRealmAuthenticator());
        List<Realm> realms = new ArrayList<>();
        //添加多个Realm
        realms.add(ShiroRealmPC());
        realms.add(ShiroRealmMini());
        securityManager.setRealms(realms);
        // 自定义缓存实现 使用redis
        //securityManager.setCacheManager(cacheManager());
        // 自定义session管理 使用redis
        //securityManager.setSessionManager(sessionManager());
        //注入记住我管理器;
        //securityManager.setRememberMeManager(rememberMeManager());
        return securityManager;
    }

    /**
     *  开启shiro aop注解支持.
     *  使用代理方式;所以需要开启代码支持;
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

    @Bean(name="simpleMappingExceptionResolver")
    public SimpleMappingExceptionResolver createSimpleMappingExceptionResolver() {
        SimpleMappingExceptionResolver r = new SimpleMappingExceptionResolver();
        Properties mappings = new Properties();
        mappings.setProperty("DatabaseException", "databaseError");//数据库异常处理
        mappings.setProperty("UnauthorizedException","403");
        r.setExceptionMappings(mappings);               // None by default
        r.setDefaultErrorView("error");                 // No default
        r.setExceptionAttribute("ex");                  // Default is "exception"
        r.setWarnLogCategory("example.MvcLogger");      // No default
        return r;
    }
}
  1. 自定义CustomizedModularRealmAuthenticator 并继承 ModularRealmAuthenticator
  2. 自定义CustomizedToken 并继承 UsernamePasswordToken
  3. 自定义ShiroRealmMini ,可以写很多很多个这样的Realm
  4. ShiroConfig 中配置 ShiroRealmMini等Realm
  5. 然后就可以了
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

神奇的网友

day day up

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值