思路比較簡單,實現也簡單,要的就是簡單! 實際項目中可以此基礎上封裝
重寫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 方法。如下圖: