免密登录常用于短信验证码或第三方应用的无缝登录体验。以下将介绍一种简单而有效的实现方式,当然,您也可以探索其他更多的方法。
package com.ruoyi.framework.shiro.token;
/**
* 定义登录方式的枚举类型
*/
public enum LoginType
{
/**
* 密码登录方式
*/
PASSWORD("password"),
/**
* 免密码登录方式
*/
NOPASSWD("nopasswd");
private String description;
LoginType(String description)
{
this.description = description;
}
public String getDescription()
{
return description;
}
}
package com.ruoyi.framework.shiro.token;
import org.apache.shiro.authc.UsernamePasswordToken;
/**
* 自定义用户登录令牌
*/
public class UserToken extends UsernamePasswordToken
{
private static final long serialVersionUID = 1L;
private LoginType loginType;
public UserToken() {}
public UserToken(String username, String password, LoginType loginType, boolean rememberMe)
{
super(username, password, rememberMe);
this.loginType = loginType;
}
public UserToken(String username, LoginType loginType)
{
super(username, "", false, null);
this.loginType = loginType;
}
public UserToken(String username, String password, LoginType loginType)
{
super(username, password, false, null);
this.loginType = loginType;
}
public LoginType getLoginType()
{
return loginType;
}
public void setLoginType(LoginType loginType)
{
this.loginType = loginType;
}
}
/**
* 登录认证方法
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException
{
UserToken userToken = (UserToken) token;
LoginType loginType = userToken.getLoginType();
String username = userToken.getUsername();
String password = userToken.getPassword() != null ? new String(userToken.getPassword()) : "";
User user;
try
{
if (LoginType.PASSWORD.equals(loginType))
{
user = loginService.login(username, password);
}
else if (LoginType.NOPASSWD.equals(loginType))
{
user = loginService.login(username);
}
}
catch (CaptchaException e)
{
throw new AuthenticationException(e.getMessage(), e);
}
catch (UserNotExistsException e)
{
throw new UnknownAccountException(e.getMessage(), e);
}
catch (UserPasswordNotMatchException e)
{
throw new IncorrectCredentialsException(e.getMessage(), e);
}
catch (UserPasswordRetryLimitExceedException e)
{
throw new ExcessiveAttemptsException(e.getMessage(), e);
}
catch (UserBlockedException | RoleBlockedException e)
{
throw new LockedAccountException(e.getMessage(), e);
}
catch (Exception e)
{
log.info("用户[{}]登录验证失败: {}", username, e.getMessage());
throw new AuthenticationException(e.getMessage(), e);
}
return new SimpleAuthenticationInfo(user, password, getName());
}
/**
* 免密码登录方法
*/
public User login(String username)
{
// 校验验证码
if (!StringUtils.isEmpty(ServletUtils.getRequest().getAttribute(ShiroConstants.CURRENT_CAPTCHA)))
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
throw new CaptchaException();
}
if (StringUtils.isEmpty(username))
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("not.null")));
throw new UserNotExistsException();
}
// 校验用户名长度
if (username.length() < UserConstants.USERNAME_MIN_LENGTH || username.length() > UserConstants.USERNAME_MAX_LENGTH)
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
throw new UserPasswordNotMatchException();
}
// 查询用户信息
User user = userService.selectUserByLoginName(username);
if (user == null)
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.not.exists")));
throw new UserNotExistsException();
}
if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.delete")));
throw new UserDeleteException();
}
if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.blocked", user.getRemark())));
throw new UserBlockedException();
}
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
recordLoginInfo(user);
return user;
}
UserToken token = new UserToken(username, LoginType.NOPASSWD);
Subject subject = SecurityUtils.getSubject();
subject.login(token);
通过以上步骤,您可以实现用户的免密登录配置,提升用户体验,同时也为系统提供了灵活的认证方式。
powered by kaifamiao