shiro 字段不是username 和password_Shiro多Realm下登录混淆问题

第一次遇到这个问题,Shiro框架若配置了多个Realm,并不是将remlm添加到SecurityManager就完事,这样情况下多个realm在登录subject.login(token)时调用的还是同一个UsernamePasswordToken,这种情况下会出现两种权限的账号密码通用,所以必须自定义一个带登录权限的Token(UsernamePasswordUserTypeToken)

00a100370b1a485068cd1f20071c1e1d.png

import org.apache.shiro.authc.UsernamePasswordToken;public class MyToken extends UsernamePasswordToken {    private String loginType;    public MyToken(String username, String password,String loginType){        super(username,password);        this.loginType=loginType;    }    public String getLoginType() {        return loginType;    }    public void setLoginType(String loginType) {        this.loginType = loginType;    }}

MyToken继承了UsernamePasswordToken,比父类多了loginType变量,接受登录账号的类型

另外,接收后的逻辑判断如下,默认会调用realm里面的doGetAuthenticationInfo方法进行身份验证,所以要继承并重写此方法,在用我们重写的方法替换掉原来代码的认证器!!!

package com.happ.config;import com.google.inject.internal.cglib.core.$Customizer;import org.apache.shiro.authc.AuthenticationException;import org.apache.shiro.authc.AuthenticationInfo;import org.apache.shiro.authc.AuthenticationToken;import org.apache.shiro.authc.Authenticator;import org.apache.shiro.authc.pam.ModularRealmAuthenticator;import org.apache.shiro.realm.Realm;import java.util.ArrayList;import java.util.Collection;public class MyAuthenticator extends ModularRealmAuthenticator {    @Override    protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {        // 判断realm是否为空        assertRealmsConfigured();        // 将authenticationToken强转为MyToken        MyToken myToken=(MyToken) authenticationToken;        // 获取myToken的登录类型        String loginType=myToken.getLoginType();        // Realms集合        Collection<Realm> realms=getRealms();        // 登录类型集 typeRealms        Collection<Realm> typeRealms=new ArrayList<>();        for(Realm realm:realms){            if (realm.getName().contains(loginType)){                typeRealms.add(realm);            }        }        if (typeRealms.size()==1){            // 长度为1 执行单一SingleRealmAuthentication            return doSingleRealmAuthentication(typeRealms.iterator().next(), myToken);        }else {            // 长度不为1 执行多个MultiRealmAuthentication            return doMultiRealmAuthentication(typeRealms,myToken);        }    }}
@Bean(name="authenticator")public Authenticator getAuthenticator(){    return new MyAuthenticator();}
@Bean(name = "securityManager")public DefaultWebSecurityManager getSecurityManager(@Qualifier("myRealm") MyRealm myRealm,@Qualifier("teacherRealm") TeacherRealm teacherRealm,@Qualifier("authenticator") Authenticator authenticator){    DefaultWebSecurityManager SecurityManager = new DefaultWebSecurityManager();    SecurityManager.setAuthenticator(authenticator);    List realms=new ArrayList<>();    realms.add(myRealm);    realms.add(teacherRealm);    SecurityManager.setRealms(realms);    return SecurityManager;}

一定要先配置认证器,再配置Realms集合,这样验证方法成功后会进入自己配置的认证器,登录接口之一:

@RequestMapping("/loginData")public String loginData(String num, String password, Model model){    // 获取当前 subject    Subject subject = SecurityUtils.getSubject();    ByteSource credentialsSalt=ByteSource.Util.bytes(num);    SimpleHash md5 = new SimpleHash("MD5", password, credentialsSalt, 1);    password=md5.toString();    // 创建 UsernamePasswordToken 令牌    MyToken token = new MyToken(num,password, MyRealm.class.getName());//        token.setRememberMe(true);    Session session = subject.getSession();    session.setAttribute("username",num);    try{        // 令牌登录        subject.login(token);        model.addAttribute("login",num);        // 登录成功返回欢迎页        return "Students/happy";    }catch (Exception ice) {        model.addAttribute("msg","账号或密码不正确");        return "Students/login";    }}

通过反射动态获取到此接口绑定的Realm名,传入认证器后将传入的权限字段放入权限集合再进行判断,如果只有一个权限,执行单一认证,反之多重认证,账号混淆问题终于解决!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值