思路比较简单,实现也简单,要的就是简单! 实际项目中可以此基础上封装
重写UsernamePasswordToken 中 getCredentials() 方法。所以新增了类NoPwdToken
在UserRealm类中的 doGetAuthenticationInfo(AuthenticationToken authcToken) 方法执行时,判断参数authcToken的类型如果是NoPwdToken类型,则返回值改为getCredentials()方法对应的验证信息。(即:SimpleHash simpleHash = new SimpleHash("SHA-256", "123456", null, 16);)。
1、增加类:NoPwdToken (关键地方是20行重写的方法)
import org.apache.shiro.authc.UsernamePasswordToken;
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() {
//这里和下方的123456对应,也可以别的,一致即可。
return "123456";
}
}
2、修改UserRealm类中 的 doGetAuthenticationInfo(AuthenticationToken authcToken) 方法。(关键地方是2-13行)
// 判断是否免密登陆类型
if (authcToken instanceof NoPwdToken) {
// 免密登陆
NoPwdToken token = (NoPwdToken) authcToken;
SysUserEntity user = sysUserDao.selectByUserName(token.getUsername());
if (user != null) {
//这里和上面的123456对应,也可以别的,一致即可。
SimpleHash simpleHash = new SimpleHash("SHA-256", "123456", null, 16);
return new SimpleAuthenticationInfo(user, simpleHash, this.getClass().getSimpleName());
} else {
return null;
}
} else {
// 默认的登陆方式
UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
user.setUsername(token.getUsername());
}
测试:
/**
* 免密登陆
*/
@SysLog("免密登陆")
@ResponseBody
@RequestMapping(value = "/sys/nopwdlogin")
public R nopwdlogin(@RequestParam Map<String, String> params, HttpServletRequest req, HttpServletResponse res) {
String username = params.get("username");
try {
if (StringUtil.isBlank(username)) {
return R.error("用户名不能为空");
}
Subject subject = SecurityUtils.getSubject();
if (null != subject.getPrincipal()) {
// 已经登陆过的情况
res.sendRedirect("http://localhost/web/index.html");
return R.ok().put("user", ShiroUtils.getUserEntity());
}
// 使用自定义Token
NoPwdToken ssoToken = new NoPwdToken(username);
subject.login(ssoToken);
} catch (UnknownAccountException e) {
return R.error(e.getMessage());
} catch (IncorrectCredentialsException e) {
return R.error("账号或密码不正确");
} catch (LockedAccountException e) {
return R.error("账号已被锁定,请联系管理员");
} catch (AuthenticationException e) {
return R.error("账户验证失败");
} catch (Exception e) {
return R.error("未知异常");
}
SysUserEntity sysUser = ShiroUtils.getUserEntity();
sysUser.setPassword(null);
try {
res.sendRedirect("http://localhost/web/index.html");
} catch (IOException e) {
e.printStackTrace();
}
return R.ok().put("user", sysUser);
}
发送请求:http://localhost:9000/sys/nopwdlogin?username=yuer
其他问题:
1、如果加密类型和上方不同,可以参考 org.apache.shiro.authc.credential.HashedCredentialsMatcher 中 hashProvidedCredentials 方法。断点打在这里就可以看到了,如图
2、用户输入密码和实际密码比较方法具体位置在 org.apache.shiro.authc.credential.HashedCredentialsMatcher 中 doCredentialsMatch 方法。如下图: