一企量、前言
需求:對(duì)接第三方登陸,實(shí)現(xiàn)繞過(guò)原有Shiro認(rèn)證登陸闹伪。
網(wǎng)上例子都有沪铭,基本都可以用壮池,反正我也抄別人的。
二杀怠、實(shí)現(xiàn)方案
1. 實(shí)現(xiàn)UsernamePasswordToken
/**
* @author jihongyuan
* @date 2020/1/8 14:42
* 自定義token 繼承UsernamePasswordToken,
* 賬號(hào)密碼登陸(password) 和 免密登陸(nopassword)
*/
public class EasyUsernameToken extends UsernamePasswordToken {
private static final long serialVersionUID = -2564928913725078138L;
private LoginType type;
public EasyUsernameToken() {
super();
}
/**
* 免密登錄
*/
public EasyUsernameToken(String username) {
super(username, "", false, null);
this.type = LoginType.NOPASSWD;
}
/**
* 賬號(hào)密碼登錄
*/
public EasyUsernameToken(String username, String password, boolean rememberMe) {
super(username, password, rememberMe, null);
this.type = LoginType.PASSWORD;
}
public LoginType getType() {
return type;
}
public void setType(LoginType type) {
this.type = type;
}
}
代碼都很簡(jiǎn)單椰憋,沒(méi)什么要說(shuō)的
2. LoginType枚舉
public enum LoginType {
/** 密碼登錄 */
PASSWORD("password"),
/** 密碼登錄 */
NOPASSWD("nopassword");
/** 狀態(tài)值 */
private String code;
private LoginType(String code) {
this.code = code;
}
public String getCode() {
return code;
}
}
3. 實(shí)現(xiàn)HashedCredentialsMatcher
public class EasyCredentialsMatch extends HashedCredentialsMatcher {
/**
* 重寫方法
* 區(qū)分 密碼和非密碼登錄
* 此次無(wú)需記錄登錄次數(shù) 詳情看SysPasswordService
*/
@Override
public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
EasyUsernameToken easyUsernameToken = (EasyUsernameToken) token;
//免密登錄,不驗(yàn)證密碼
if (LoginType.NOPASSWD.equals(easyUsernameToken.getType())) {
return true;
}
//密碼登錄
Object tokenHashedCredentials = hashProvidedCredentials(token, info);
Object accountCredentials = getCredentials(info);
return equals(tokenHashedCredentials, accountCredentials);
}
}
代碼都很簡(jiǎn)單,沒(méi)啥要注意的赔退。
4. Spring Boot配置
@Bean
public EasyCredentialsMatch customCredentialsMatch() {
EasyCredentialsMatch customCredentialsMatch = new EasyCredentialsMatch();
customCredentialsMatch.setHashAlgorithmName("md5");
customCredentialsMatch.setHashIterations(3);
customCredentialsMatch.setStoredCredentialsHexEncoded(true);
return customCredentialsMatch;
}
5. 實(shí)現(xiàn)AuthorizingRealm
public class UserRealm extends AuthorizingRealm {
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
......................
}
/**
* 登錄認(rèn)證
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
EasyUsernameToken upToken = (EasyUsernameToken) token;
String username = upToken.getUsername();
SysUser user = null;
// 密碼登錄
if (upToken.getType().getCode().equals(LoginType.PASSWORD.getCode())) {
String password;
if (upToken.getPassword() != null) {
password = new String(upToken.getPassword());
try {
user = loginService.login(username, password);
} ......
catch (Exception e) {
log.info("對(duì)用戶[" + username + "]進(jìn)行登錄驗(yàn)證..驗(yàn)證未通過(guò){}", e.getMessage());
throw new AuthenticationException(e.getMessage(), e);
}
}
} else if (upToken.getType().getCode().equals(LoginType.NOPASSWD.getCode())) {
// 第三方登錄
......
}
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, upToken.getPassword(), getName());
return info;
}
}
6. 使用
private AjaxResult login(String username, String password, Boolean rememberMe) {
EasyUsernameToken token = new EasyUsernameToken(username, password, rememberMe);
Subject subject = SecurityUtils.getSubject();
try {
subject.login(token);
return success();
} catch (AuthenticationException e) {
String msg = "用戶或密碼錯(cuò)誤";
if (StringUtils.isNotEmpty(e.getMessage())) {
msg = e.getMessage();
}
return error(msg);
}
}
三橙依、總結(jié)
代碼都網(wǎng)上抄的,找不到原文了硕旗。
注意一下強(qiáng)轉(zhuǎn)EasyUsernameToken就好窗骑。
代碼非常的簡(jiǎn)單!F崦丁创译!