如何用node.js进行token身份验证?

807 阅读3分钟

最近想要给我的博客系统添加一个基于node.js服务器的token身份验证的功能,要求用户进行登录操作后的3小时内可以进行评论操作,但登录超过3小时则要重新进行登录,否则不能对文章进行评论。

废话不多说,直接说方法:

1. 来到node.js服务端,需要额外下载的插件

npm i express-jwt --save
npm i jsonwebtoken --save

2. 在router.js中引入

const jwt = require('jsonwebtoken');
const { format } = require('path');
const SECRET_KEY = 'login2022';

3. 当用户第一次登录成功之后,服务端给客户端返回相关资源的同时生成并发送一串token命令

// 这是一个常规的登录接口
router.post('/api/login', function (req, res) {
    let { body } = req
    var sqlStr = `SELECT * FROM usermanage WHERE user_name='${body.user_name}' AND user_password='${body.user_password}'`;
    conn.query(sqlStr, function (err, results) {
        if (err) {
            res.json({ code: 1, msg: err });
        }
        else {
            if (results.length == 0) {
                res.json({ code: 2, msg: '未找到该用户' });
            } else {
                // 以上是常规的登录流程,查找数据库是否有用户的信息,以下是添加token的流程
                // 如果登录成功,则用jwt.sign签署token令牌,最基本的令牌由用户的基本信息 + 一个自定义的字符串 + 有效时间 构成, 也可以加上当前时间戳
                let token = jwt.sign(
                    { user: { name: results[0].user_name, password: results[0].user_password } }, //用户信息
                    SECRET_KEY, //自定义字符串
                    { expiresIn: '3h' } //有效时间,这里我设置3个小时
                )
                res.json({ code: 0, list: results, token }); //最后,将资源和token令牌一并发送给客户端。
            }

        }
    });
});

4. 接下来来到前端部分,客户端将从后端传递过来的token令牌存储到本地

localStorage.setItem("token", res.data.token);

5. 然后,对我们的请求方法进行一个封装,要求每一个前端向服务器发请求时,都要发送一个包含token的Authorization请求头

以下是我自己项目的封装方法
const $http = axios.create({
    baseURL: 'http://localhost:3000/api',
    timeout: 5000,
    //下面是重点
    headers: {
        'Content-Type': "application/json;charset=utf-8",
        //注意:这个Bearer是必需的,如果后端没有添加 'Bearer ', 则需要前端自己拼接
        //从本地获取token
        'Authorization': 'Bearer '+ window.localStorage.getItem('token')
    }
})

好了,现在前端部分已经搞定了,我们返回后端进行下一步操作。

在服务端新建一个errorhandler文件,里面写入以下方法,生成一个专门发送token错误的中间件:

function errorHandler(err, req, res, next) {
    console.log(err, err.name);
    let code = 500;
    let message = 'Internal Server Error';
    // token解析的错误
    if (err.name === 'UnauthorizedError') {
      code = 401
      message = 'no login'
    }
    res.statusCode = code;
    res.send({
      status: code,
      message,
    })
  }
  
  module.exports = errorHandler

6. 来到服务器的入口文件index.js,引入插件

//创建服务器
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
//引入parseJwt
const parseJwt = require("express-jwt");
//引入token错误中间件
const errorhandler = require('./errorhandler')

7. 对从服务器返回的token令牌进行解析

//这里是对所有的请求接口都进行token验证
app.use(parseJwt({
    secret: 'login2022', // 生成token时的 钥匙,必须统一
    algorithms: ['HS256'] // 必填,加密算法
  }).unless({
    path: ['/api/login'] // 一般来说,登录接口不需要进行token验证,所以可以用.unless避免对该接口的验证,当然也可以添加其它的接口
  }));
  
  //使用token错误中间件,如果token失效或过期,则向前端发送相关报文
  app.use(errorhandler)

9. 至此,一个简单的token验证就完成了,如果用户登录超时,则会返回以下错误信息:

image.png