Node.js - 项目实践之登录注册(三)

194 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情

项目要求

通过一个小项目实践 Node.js 各个知识点。麻雀虽小,五脏俱全,这个项目会从 0~1,逐步完成所有需求。该项目实现接口有注册、登录、获取用户信息等等

截屏2022-05-28 下午11.35.33.png


登录注册

实现步骤
  • 检测表单数据是否合法
  • 根据用户名查询用户的数据
  • 判断用户输入的密码是否正确
  • 生成 JWT 的 Token 字符串
检测登录表单的数据是否合法
  • /router/user.js 中,登录的路由代码修改如下

    // 用户登录
    router.post('/login', expressJoi(reg_login_schema), userHandler.login)
    
根据用户名查询用户的数据
  1. 接收表单数据

    const userInfo = req.body
    
  2. 定义 SQL 语句

    // 定义 SQL 语句
    const sql = 'select * from ev_users where username=?'
    
  3. 执行 SQL 语句,查询用户的数据

    // 执行 SQL 语句,根据用户名查询用户的信息
    db.query(sql, userInfo.username, (err, results) => {
        // 执行 SQL 语句失败
        if(err) return res.cc(err)
        // 执行 SQL 语句成功,但是获取到的数据条数不等于1
        if (results.length !== 1) return res.cc('登录失败!')
        // TODO: 判断密码是否正确
        res.send('login ok')
    })
    
判断用户输入的密码是否正确
  • 核心实现思路:调用 bcrypt.compareSync (用户提交的密码,数据库中的密码) 方法比较密码是否一致。返回值是布尔值 (true 一致,false 不一致)

  • 代码实现:

    // 使用用户输入的密码,和数据库中存储的密码进行对比
    const compareResult = bcrypt.compareSync(userInfo.password, results[0].password)
    
    // 如果对比的结果是 false 则证明用户密码不对
    if (!compareResult){
        return res.cc('登录失败')
    }
    
生成 JWT 的 Token 字符串

核心注意点: 在生成 Token 字符串的时候,一定要先剔除密码和头像的值

  1. 通过 ES6 的高级语法,快速剔除 密码 和 头像 的值

    const user = {...results[0], password: '', user_pic:''}
    
    
    /*
    user的值:
    {
        id: 7,
        username: 'admin6',
        password: '',
        nickname: null,
        email: null,
        user_pic: ''
    }
    */
    
  2. 运行如下命令,安装生成的 Token 字符串的包

    npm install jsonwebtoken@8.5.1
    
  3. /router_handler/user.js 模块的头部区域,导入 jsonwebtoken

    // 导入生成 Token 的包
    const jwt = require('jsonwebtoken')
    
  4. 创建 config.js 文件,并向外共享加密和还原 Token 的 jwtsecreKey 字符串

    const expressJoi = require("@escook/express-joi");
    
    // 这是一个全局的配置文件
    module.exports = {
        // 加密和解密 Token 的秘钥
        jwtSecretKey: 'studyNode.',
        // Token 的有效期
        expiresIn: '10h'
    }
    
  5. 将用户信息对象加密成 Token 字符串

    // 导入全局的配置文件
    const config = require('../config')
    // 对用户信息进行加密,生成 Token 字符串
    const tonkenStr = jwt.sign(user,config.jwtSecretKey, { expiresIn: config.expiresIn})
    
  6. 将生成的 Token 字符串响应给客户端

    // 调用 res.send() 将 Token 响应给客户端
    res.send({
        status:0,
        message:'登录成功',
        token:'Bearer ' + tonkenStr
    })
    

配置解析 Token 的中间件
  1. 运行如下命令,安装解析 Token 的中间件

    npm install express-jwt
    
  2. app.js 中注册路由之前,配置解析 Token 的中间件

    // 解析 token的中间件
    var { expressjwt: expJWT } = require("express-jwt")
    
    // 导入配置文件
    const config = require('./config')
    
    // 使用 .unless({ path:[/^\/api\//] }) 指定哪些接口不需要进行 token 的身份验证
    app.use(
        expJWT({
        secret: config.jwtSecretKey,
        algorithms: ["HS256"],
        }).unless({ path:[/^\/api\//] })
    )
    
  3. app.js 中的错误级别中间件,捕获并处理 Token 认证失败后的错误

    // 定义错误级别的中间件
    app.use((err, req, res, next) => {
        // 验证失败导致的错误
        if (err instanceof joi.ValidationError) return res.cc(err)
        // 身份认证失败的错误
        if (err.name === 'UnauthorizedError') return res.cc('身份认证失败')
    
        // 未知的错误
        res.cc(err)
    })