RuoYi-Vue-Plus之密码登录
文档地址:点击这里
项目地址:点击这里
SaToken文档:点击这里
密码登录简单介绍
密码登录也就是直接登录

具体实现方法
@Override
public LoginVo login(String body, SysClient client) {
PasswordLoginBody loginBody = JsonUtils.parseObject(body, PasswordLoginBody.class);
// 校验参数
ValidatorUtils.validate(loginBody);
// 租户id
String tenantId = loginBody.getTenantId();
String username = loginBody.getUsername();
String password = loginBody.getPassword();
String code = loginBody.getCode();
String uuid = loginBody.getUuid();
boolean captchaEnabled = captchaProperties.getEnable();
// 验证码开关
if (captchaEnabled) {
validateCaptcha(tenantId, username, code, uuid);
}
// 通过用户名查询用户:下面会具体介绍该方法
SysUserVo user = loadUserByUsername(tenantId, username);
loginService.checkLogin(LoginType.PASSWORD, tenantId, username, () -> !BCrypt.checkpw(password, user.getPassword()));
// 此处可根据登录用户的数据不同 自行创建 loginUser
LoginUser loginUser = loginService.buildLoginUser(user);
loginUser.setClientKey(client.getClientKey());
loginUser.setDeviceType(client.getDeviceType());
SaLoginModel model = new SaLoginModel();
// 设置设备类型
model.setDevice(client.getDeviceType());
// 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置
// 例如: 后台用户30分钟过期 app用户1天过期
// 设置token有效期
model.setTimeout(client.getTimeout());
// 设置token最低活跃频率,例如:设置token最低活跃评率为30分钟,如果在30分钟内没有进行任何操作,则token过期
model.setActiveTimeout(client.getActiveTimeout());
// 设置扩展信息
// Token挂载的扩展参数 (此方法只有在集成jwt插件时才会生效)
model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId());
// 生成token
LoginHelper.login(loginUser, model);
LoginVo loginVo = new LoginVo();
loginVo.setAccessToken(StpUtil.getTokenValue());
loginVo.setExpireIn(StpUtil.getTokenTimeout());
loginVo.setClientId(client.getClientId());
return loginVo;
}loadUserByUsername方法
private SysUserVo loadUserByUsername(String tenantId, String username) {
return TenantHelper.dynamic(tenantId, () -> {
SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
.select(SysUser::getUserName, SysUser::getStatus)
.eq(SysUser::getUserName, username));
if (ObjectUtil.isNull(user)) {
log.info("登录用户:{} 不存在.", username);
throw new UserException("user.not.exists", username);
} else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
log.info("登录用户:{} 已被停用.", username);
throw new UserException("user.blocked", username);
}
return userMapper.selectUserByUserName(username);
});
}一开始我也疑惑,看方法名不是通过username查询User吗,为什么还要传输tenantId呢。因为这是多租户框架,我们在查询一些特定的表需要拼接tenantId,类似于数据权限,但是不同于数据权限。由于数据库username可能会有多个,但是tenantId+username是唯一的。这里就体现了数据隔离。
小结:进行登录时,查询用户时会在where语句拼接tenantId,这里的tenantId由前端传递而来,然后设置到当前线程中,当查询完毕时,tenantId在当前线程中被移除。
LoginHelper.login方法
/**
* 登录系统 基于 设备类型
* 针对相同用户体系不同设备
*
* @param loginUser 登录用户信息
* @param model 配置参数
*/
public static void login(LoginUser loginUser, SaLoginModel model) {
// 设置信息到请求中
SaStorage storage = SaHolder.getStorage();
storage.set(LOGIN_USER_KEY, loginUser);
storage.set(TENANT_KEY, loginUser.getTenantId());
storage.set(USER_KEY, loginUser.getUserId());
storage.set(DEPT_KEY, loginUser.getDeptId());
model = ObjectUtil.defaultIfNull(model, new SaLoginModel());
// 登录工作由SaToken自动完成
StpUtil.login(loginUser.getLoginId(),
model.setExtra(TENANT_KEY, loginUser.getTenantId())
.setExtra(USER_KEY, loginUser.getUserId())
.setExtra(DEPT_KEY, loginUser.getDeptId()));
// 获取token会话
SaSession tokenSession = StpUtil.getTokenSession();
// 更新token过期时间
tokenSession.updateTimeout(model.getTimeout());
// 设置属性
tokenSession.set(LOGIN_USER_KEY, loginUser);
}RuoYi-Vue-Plus之密码登录
http://example.com/2024/05/11/RuoYi-Vue-Plus之密码登录/