登陆逻辑:

  1. 拿到用户名,密码(mysql);验证码,验证码的Key(redis)(本文暂未做验证码)
  2. 先校验验证码的正确性(redis);从mysql数据库里面查询用户(mysql);
  3. 密码的匹配;
  4. 生成token(2h后过期)(redis);refresh_token(30d过期)(mysql);生成一个tokenKey(cookie);

前置参考文章

  1. 本文使用了自定义统一返回数据格式,详情参见文章:
    云剪切板——统一后端返回数据格式
  2. 本文使用了nodejs连接mysql文章中封装后的查询数据库方法,详情参见文章:
    Nodejs express 连接Mysql
  3. 本文使用了nodejs连接redis文章中封装后的方法,详情参见文章:
    Nodejs express 连接 Redis

目录文件结构

server
├─controllers
│  ├─RouterController.js
│  └─UserController.js
├─daos
│  ├─TokenDAO.js
│  └─UserDAO.js
├─dtos
│  └─UserDTO.js
├─services
│  ├─MysqlService.js
│  ├─RedisService.js
│  └─UserService.js
├─utils
│  ├─Constances.js
│  ├─Result.js
│  └─ResultCode.js
└─App.js
shell

主要代码

UserDTO

  • UserDTO.js
module.exports  = class UserDTO{

    /**
     * id
     */
    id;

    /**
     * 用户名
     */
    name;

    /**
     * 邮箱
     */
    email;

    /**
     * 额度
     */
    count;
    
    constructor(data) {
        this.id = data.id;
        this.name = data.name;
        this.email = data.email;
        this.count = data.count;
    }
}
js

UserDao

  • UserDao.js
import {Query} from "../services/MysqlService";

export function getUser(username) {
    return Query("SELECT * FROM `tb_user` WHERE `name` = ? OR `email` =  ? ",[username,username])
}

js

UserController

  • UserController.js
const express = require("express")
const UserController = express.Router();
const UserService = require("../services/UserService")

UserController.post("/login",UserService.login)

module.exports = UserController
js

RouterController

  • RouterController.js
const UserController = require("./UserController")

module.exports =(app)=>{
    app.use("/user",UserController)
}
js

App

  • App.js
const express = require("express");
const Router = require("./controllers/RouterController")
const app = express();

app.use(express.json())

Router(app)

module.exports ={
    path:"api",
    handler:app
}
js

MysqlService

  • MysqlService.js
const MysqlPoolConfig = {
    host: "localhost",
    port: "****",
    user: "****",
    password: "*****",
    database: "clipboard",
    connectionLimit:20
}

const mysql = require("mysql");

let pool = mysql.createPool(MysqlPoolConfig);

export const Query = (sql = "", params = []) => {
    return new Promise((resolve, reject) => {
        pool.getConnection((err, conn) => {
            if (err) reject(err)
            else conn.query(sql, params, (error, result, fields) => {
                if (error) reject(error)
                else resolve(result)
            })
        })
    })
}
js

RedisService

  • RedisService.js
const redis = require("redis");

const RedisConfig={
    url:"redis://:***@localhost:0000"
}

const RedisClient = redis.createClient(RedisConfig)

RedisClient.connect()
    .then(() => {
        console.log("Redis Connect Success....")
    })
    .catch(err => {
        console.log("Redis Connect Error....",err)
    })


export const RedisService = ()=>{
    return RedisClient
}
js

Contances

  • Contances.js
export  const JWTSecret = "*******"

export const KEY  ={
    TOKEN:"token_",
    COOKIE:"auth"
}

export const VALUE = {
    PLATFORM:{
        WEB:"web",
        ANDROID:"android",
        WINDOWS:"windows"
    }
}
js

UserService——核心

使用bcryptjs验证密码:

bcrypt.compareSync(password, passFromDB)
js

使用jwt生成token:

jwt.sign({...userDTO}, JWTSecret, {expiresIn: "30d"})
js
  • UserService.js
import {RedisService} from "./RedisService";
import {JWTSecret, KEY, VALUE} from "../utils/Constances";

const UserDTO = require("../dtos/UserDTO");

const Result = require("../utils/Result");
const UserDao = require("../daos/UserDao");
const TokenDao = require("../daos/TokenDao");

const validator = require("express-validator");

const bcrypt = require("bcryptjs")

const jwt = require("jsonwebtoken")

export const login = [
    validator.body("username", "用户名不能为空").isLength({min: 1}),
    validator.body("password", "密码不能为空").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} = req.body;

        if(!platform) platform = VALUE.PLATFORM.WEB

        // 2. 先校验验证码的正确性(redis);从mysql数据库里面查询用户(mysql);
        //TODO: redis captcha

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

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

                // 4. 生成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*60*60})

                return Result.result(res, Result.success(userDTO));
            })
            .catch(err => {
                console.log(err)
                return Result.result(res,Result.failed("登陆失败"))
            })
    }]
js

参考内容

  1. 【续加仪 云剪切板——统一后端返回数据格式】: https://www.hyz.cool/articles/209
  2. 【续加仪 Nodejs express 连接Mysql】: https://www.hyz.cool/articles/207
  3. 【续加仪 Nodejs express 连接 Redis】: https://www.hyz.cool/articles/208
  4. 【NPM mysql】: https://www.npmjs.com/package/mysql
  5. 【NPM redis】: https://www.npmjs.com/package/redis
  6. 【NPM bcryptjs】: https://www.npmjs.com/package/bcryptjs
  7. 【NPM express-validator】: https://www.npmjs.com/package/express-validator
  8. 【NPM jsonwebtoken】: https://www.npmjs.com/package/jsonwebtoken
打赏
  • 微信
  • 支付宝
评论
来发评论吧~
···

歌手: