shiro三方免密登录的简单实现方式
用户输入密码和实际密码比较方法具体位置在 org.apache.shiro.authc.credential.HashedCredentialsMatcher 中 doCredentialsMatch 方法:
1.自定义一个NoPwdToken类继承UsernamePasswordToken方法,重写getCredentials()方法。
public class NoPwdToken extends UsernamePasswordToken {
public NoPwdToken(String username) {
this.username = username;
}
private String username;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public Object getCredentials() {
//构建假的密码,也可以是别的,和后面SimpleAuthenticationInfo中加密的假密码对应一致即可
return "123456";
}
}
2.改造自定义realm中doGetAuthenticationInfo认证方法:
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//如果是免密登录
if(token instanceof NoPwdToken){
NoPwdToken token1 = (NoPwdToken) token;
String username = token1.getUsername();
//这里模拟根据用户名去数据库查询用户信息
User user = new User();
user.setUsername(username);
user.setPassword("8a4483314347c12508a96e4183c9b2d0");
user.setSalt("quyi");
//判断是否查询到
if (user != null) {
//这里和重写的getCredentials()方法返回值对应一致
String mima = MD5Util.md5_private_salt("123456",user.getSalt());
return new SimpleAuthenticationInfo(
user,//传用户名或者user对象
mima,
ByteSource.Util.bytes(user.getSalt()),//加密的盐值
getName());//当前realm的名字
} else {
throw new UnknownAccountException("用户不存在");
}
}
//如果不是免密登录执行下面其他的方法
......
}
这里注意盐值的问题,如果根据假密码加密的时候添加了盐值( String mima = MD5Util.md5_private_salt(“123456”,user.getSalt());),那么在SimpleAuthenticationInfo构造方法中也要加上相同的盐值,我这里用的都是user.getSalt()这个盐值。
3.免密登录接口
@PostMapping("/login3")
public String login3(){
//模拟三方登录认证成功 并拿到了用户信息
String username = "admin";
Subject subject = SecurityUtils.getSubject();
//这里使用我们自定义的NoPwdToken类
NoPwdToken noPwdToken = new NoPwdToken(username);
try {
subject.login(noPwdToken);
//将authorization传给前端,用于MySessionManager中请求的验证
return (String)subject.getSession().getId();
}catch (UnknownAccountException e){
e.printStackTrace();
System.out.println("未知账户/没找到帐号");
return "未知账户/没找到帐号";
}catch (IncorrectCredentialsException e){
e.printStackTrace();
System.out.println("密码错误");
return "密码错误";
}catch (Exception e){
e.printStackTrace();
System.out.println("其他异常");
return "其他异常" + e.getMessage();
}
}
tem.out.println(“其他异常”);
return “其他异常” + e.getMessage();
}
}