一、前言
需求:对接第三方登陆,实现绕过原有Shiro认证登陆。
网上例子都有,基本都可以用,反正我也抄别人的。
二、实现方案
1. 实现UsernamePasswordToken
/**
* @author jihongyuan
* @date 2020/1/8 14:42
* 自定义token 继承UsernamePasswordToken,
* 账号密码登陆(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;
}
/**
* 账号密码登录
*/
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;
}
}
代码都很简单,没什么要说的
2. LoginType枚举
public enum LoginType {
/** 密码登录 */
PASSWORD("password"),
/** 密码登录 */
NOPASSWD("nopassword");
/** 状态值 */
private String code;
private LoginType(String code) {
this.code = code;
}
public String getCode() {
return code;
}
}
3. 实现HashedCredentialsMatcher
public class EasyCredentialsMatch extends HashedCredentialsMatcher {
/**
* 重写方法
* 区分 密码和非密码登录
* 此次无需记录登录次数 详情看SysPasswordService
*/
@Override
public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
EasyUsernameToken easyUsernameToken = (EasyUsernameToken) token;
//免密登录,不验证密码
if (LoginType.NOPASSWD.equals(easyUsernameToken.getType())) {
return true;
}
//密码登录
Object tokenHashedCredentials = hashProvidedCredentials(token, info);
Object accountCredentials = getCredentials(info);
return equals(tokenHashedCredentials, accountCredentials);
}
}
代码都很简单,没啥要注意的。
4. Spring Boot配置
@Bean
public EasyCredentialsMatch customCredentialsMatch() {
EasyCredentialsMatch customCredentialsMatch = new EasyCredentialsMatch();
customCredentialsMatch.setHashAlgorithmName("md5");
customCredentialsMatch.setHashIterations(3);
customCredentialsMatch.setStoredCredentialsHexEncoded(true);
return customCredentialsMatch;
}
5. 实现AuthorizingRealm
public class UserRealm extends AuthorizingRealm {
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
......................
}
/**
* 登录认证
*/
@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("对用户[" + username + "]进行登录验证..验证未通过{}", 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 = "用户或密码错误";
if (StringUtils.isNotEmpty(e.getMessage())) {
msg = e.getMessage();
}
return error(msg);
}
}
三、总结
代码都网上抄的,找不到原文了。
注意一下强转EasyUsernameToken就好。
代码非常的简单!!!
网友评论