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之密码登录/
发布于
2024年5月11日
更新于
2024年5月18日
许可协议