增加登陆验证码

前置内容

本文代码中使用但未声名的函数请参考以下文章:

  1. 【登录实现——云剪切板—用户模块】:https://www.hyz.cool/articles/210
  2. 【检查用户登陆——云剪切板】:https://www.hyz.cool/articles/212

服务实现

  • UserService.js
/**
 * 登陆
 */
export const login = [
    validator.body("username", "用户名不能为空").isLength({min: 1}),
    validator.body("password", "密码不能为空").isLength({min: 1}),
    validator.body("captcha", "图形验证码不能为空").isLength({min: 1}),
    validator.body("captchaKey", "图形验证码Key不能为空").isLength({min: 1}),

    (req, res, next) => {

        //校验参数
        let validationResult = validator.validationResult(req);
        if (!validationResult.isEmpty()) return Result.result(res, Result.invalidParams(validationResult.array()))

        // 1. 拿到用户名,密码(mysql);验证码,验证码的Key(redis)
        let {username, password, platform, captcha, captchaKey} = req.body;

        if (!platform) platform = VALUE.PLATFORM.WEB
        
        //2. 检查是否已经登陆
        getLoginUser(req).then(userDTO => {
            return Result.result(res, Result.success(userDTO));
        }).catch(() => {
            // 3. 先校验验证码的正确性(redis);从mysql数据库里面查询用户(mysql);
            RedisService().get(KEY.CAPTCHA + captchaKey).then(result => {
                if (!result) return Result.result(res, Result.failed("验证码过期"));
                if ((result + "").toLowerCase() !== (captcha + "").toLowerCase()) return Result.result(res, Result.failed("验证码错误"));

                //从数据库中查询
                UserDao.getUser(username).then(result => {
                    if (result.length < 1) return Result.failed("用户名不正确");
                    let passFromDB = result[0].password;
                    let userDTO = new UserDTO(result[0]);

                    // 4. 密码的匹配;
                    //校验密码
                    if (!bcrypt.compareSync(password, passFromDB)) return Result.result(res, Result.failed("密码错误"));

                    // 5. 生成token(2h后过期)(redis);refresh_token(30d过期)(mysql);生成一个tokenKey(cookie);

                    let token = jwt.sign({...userDTO}, JWTSecret, {expiresIn: "2h"});

                    let refreshToken = jwt.sign({...userDTO}, JWTSecret, {expiresIn: "30d"})

                    let tokenKey = bcrypt.hashSync(refreshToken, bcrypt.genSaltSync(10))

                    //保存token到redis
                    RedisService().set(KEY.TOKEN + tokenKey, token, {EX: 2 * 60 * 60})

                    //保存refresh token到mysql
                    TokenDao.saveToken(userDTO.id, refreshToken, tokenKey, platform)

                    //保存到cookie
                    res.cookie(KEY.COOKIE, tokenKey, {maxAge: 30 * 24 * 60 * 60 * 1000})

                    RedisService().del(KEY.CAPTCHA + captchaKey)

                    //6. 返回
                    return Result.result(res, Result.success(userDTO));
                }).catch(err => {
                    console.log(err)
                    return Result.result(res, Result.failed("登陆失败"))
                })
            }).catch(err => {
                return Result.result(res, Result.failed("获取图形验证码失败"))
            })
        })
    }]
js
打赏
  • 微信
  • 支付宝
评论
来发评论吧~
···

歌手: