shiro多realm配置免密码登陆

情景:项目本身shiro集成用的是标准的用户名、密码验证,现需要与第三方平台对接,使用免密码shiro验证,需要多加一个免密码验证的realm,并保证两个realm都可用。

Shiro.xml

1、安全管理器中添加authenticator认证策略配置

<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
    <property name="authenticator" ref="authenticator"/>
    <!--<property name="realm" ref="shiroDbRealm"></property>-->
    <!--将缓存管理器,交给安全管理器-->
    <property name="cacheManager" ref="shiroSpringCacheManager"/>
    <!-- 记住密码管理 -->
    <property name="rememberMeManager" ref="rememberMeManager"/>
    <property name="sessionManager" ref="sessionManager"/>
</bean>

2、在authenticator中配置多realm和具体的认证策略

<bean id="authenticator" class="org.apache.shiro.authc.pam.ModularRealmAuthenticator">
    <!-- 多realm配置 -->
    <property name="realms">
        <list>
            <ref bean="shiroSSORealm"/> <!-- 免密码realm配置 -->
            <ref bean="shiroDbRealm"/>  <!-- 正常默认的realm配置 -->
        </list>
    </property>
    <!-- 配置认证策略 -->
    <property name="authenticationStrategy">
        <!-- 所有Realm皆匹配成功才算成功 -->
        <!--<bean class="org.apache.shiro.authc.pam.AllSuccessfulStrategy"></bean>-->
        <!-- 只要一个或者多个Realm认证通过就算成功 -->
         <bean class="org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy"></bean>
        <!-- 第一个匹配成功即算匹配成功 -->
        <!-- <bean class="org.apache.shiro.authc.pam.FirstSuccessfulStrategy"></bean> -->
    </property>
</bean>

3、注入新加的realm bean 并自定义凭证匹配规则凭证匹配规则默认实现是CredentialsMatcher类的doCredentialsMatch方法,我们需要继承该类,并重写doCredentialsMatch方法来自定义匹配规则。

<!-- 項目自定义的ssoRealm -->
<bean id="shiroSSORealm" class="com.wf.commons.shiro.ShiroSSORealm">
    <constructor-arg name="cacheManager" ref="shiroSpringCacheManager"/>
    <constructor-arg index="1" name="matcher" ref="credentialsMatcherSSO"/>
    <!-- 启用身份验证缓存,即缓存AuthenticationInfo信息,默认false -->
    <property name="authenticationCachingEnabled" value="true"/>
    <!-- 缓存AuthenticationInfo信息的缓存名称 -->
    <property name="authenticationCacheName" value="authenticationCache"/>
    <!-- 缓存AuthorizationInfo信息的缓存名称 -->
    <property name="authorizationCacheName" value="authorizationCache"/>
</bean>
<!-- sso免密码登陆 -->
<bean id="credentialsMatcherSSO" class="com.wf.commons.shiro.CredentialsMatcherSSO">
</bean>

public class CredentialsMatcherSSO implements CredentialsMatcher {
    @Override
    public boolean doCredentialsMatch(AuthenticationToken authenticationToken, AuthenticationInfo authenticationInfo) {
//验证规则写这里,因为ShiroSSORealm中已经对用户名做了判断,这里不做验证直接返回true即可
        return true;
    }
}

4、实现ShiroDbRealm类

public class ShiroSSORealm extends AuthorizingRealm {
    private static final Logger LOGGER = LogManager.getLogger(ShiroSSORealm.class);

    @Autowired private IUserService userService;
    @Autowired private IRoleService roleService;

    public ShiroSSORealm(CacheManager cacheManager, CredentialsMatcher matcher) {
        super(cacheManager,matcher);
    }

    /**
     * Shiro登录认证(原理:用户提交 用户名和密码  
     * --- shiro 封装令牌 
     * ---- realm 通过用户名将密码查询返回
     * ---- shiro 自动去比较查询出密码和用户输入密码是否一致---- 进行登陆控制 )
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(
            AuthenticationToken authcToken) throws AuthenticationException {
        LOGGER.info("Shiro开始登录认证");
//UserNameToken 是存储用户名的实体类,实现了 HostAuthenticationToken, RememberMeAuthenticationToken, Serializable接口,具体写法可参照shiro自带的UsernamePasswordToken来写

        UserNameToken token = null;

        // UserNameToken,则强转,获取username;否则不处理。
        if(authcToken instanceof UserNameToken){
            token = (UserNameToken) authcToken;
        }else{
            return null;
        }
            UserVo uservo = new UserVo();
            uservo.setLoginName(token.getUserName());
            List<User> list = userService.selectByLoginName(uservo);
            // 账号不存在
            if (list == null || list.isEmpty()) {
                return null;
            }
            User user = list.get(0);
            // 账号未启用
            if (user.getStatus() == 1) {
                return null;
            }
            // 读取用户的url和角色
            Map<String, Set<String>> resourceMap = roleService.selectResourceMapByUserId(user.getId());
            Set<String> urls = resourceMap.get("urls");
            Set<String> roles = resourceMap.get("roles");
            ShiroUser shiroUser = new ShiroUser(user.getId(), user.getLoginName(), user.getName(), urls);
            shiroUser.setRoles(roles);
            // 认证缓存信息,实际上密码的参数并没有卵用,因为我们在验证的具体方法直接返回ture了
            return new SimpleAuthenticationInfo(shiroUser, user.getPassword().toCharArray(),
                    ShiroByteSource.of(user.getSalt()), getName());

    }

    /**
     * Shiro权限认证
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(
            PrincipalCollection principals) {
        return null;
    }
    //这个重写必须加,不然报令牌验证错误,如果只有一个token估计不用
    @Override
    public boolean supports(AuthenticationToken var1){
        return var1 instanceof UserNameToken;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值