node.js中通过JSONWebToken(JWT)生成和验证token,使用全局中间件验证所有接口中token是否合法并准许特定路由绕过验证

4 阅读3分钟

JSON Web Token (JWT) 是一种用于在各方之间安全传输信息的紧凑且安全的声明。JWT 可以通过 HTTP 请求发送,并且通常用于实现无状态的认证机制(即服务器不需要保存会话状态)。JWT 是一种紧凑且自包含的令牌格式,通常用于在客户端和服务器之间传递经过认证和授权的信息。

1.安装

  • npm i jsonwebtoken:下载jwt。

2.导入

  • const jwt = require("jsonwebtoken"):导入jwt并赋值给一个变量。

3.jwt.sign()生成token

  • jwt.sign(PayloadData,SECRET_KEY,{expiresIn: 3600}):生成带载荷、密钥、过期时间的token。

jwt.sign()的参数

  • PayloadData:载荷数据,表示要存储在token中的信息。必须为对象格式,如:{openid: req.openid, userName: req.nickName }。在verify验证方法的回调内获取。
  • SECRET_KEY:用于签名的密钥,用户自定义或者通过算法生成。
  • Object:第三个参数为配置对象,最常用的就是expiresIn表示token过期时间(单位秒)。
const router = require("express").Router();
const jwt = require("jsonwebtoken");
router.post("/login", async (req, res) => {
  // sign()内 第一个参数表示要存储在token中的信息(在验证verify方法内返回的user内展示所以得为对象形式) 第二个参数表示代表了用于签名的密钥 第三个参数表示jwt过期时间单位秒
  const token = jwt.sign({ openid: req.openid },process.env.JWT_SECRET_KEY,{ expiresIn: 60 * 60 });
  res.json({
    code: 200,
    msg: '登录成功',
    token,
    openid: req.openid
  })
})

4.jwt.verify()验证token的合法性和完整性,使用全局中间件验证token是否合法并允许特定路由绕过验证

  • jwt.verify(token, SECRET_KEY,(err,user) => {}):验证JWT的合法性和完整性。

jwt.verify()的参数

  • token:需要验证的token。
  • SECRET_KEY:用于签名的密钥,用户自定义或者通过算法生成。需要与生成签名时的秘钥一样。
  • (err,user) => {}:回调函数。err报错信息,user解码后的载荷数据。

使用全局中间件验证所有接口中token是否合法并准许特定路由绕过验证

  • app.use((req, res, next) => {}):使用全局中间件验证所有接口的req请求报文中的token是否合法,如果合法则通过next()放行。在回调中写相应逻辑可以绕过特定路由的验证。
const express = require("express");
const jwt = require("jsonwebtoken");
const app = express();
// JWT 验证中间件
function authenticateToken(req, res, next) {
  const authHeader = req.headers["authorization"];
  const token = authHeader;
  if (token == null) return res.sendStatus(401); // 如果没有提供 token,则返回 401 Unauthorized
  // verify()验证JWT的合法性和完整性 第一个参数要解析的token 第二个参数是密钥 第三个参数是回调函数(err,user)
  jwt.verify(token, process.env.JWT_SECRET_KEY, (err, user) => {
    if (err) return res.sendStatus(403); // 如果 token 无效或已过期,则返回 403 Forbidden
    req.user = user; // 将解码后的用户信息附加到请求对象上
    console.log(user);
    next();
  });
}
// 设置全局中间件验证所有接口请求头是否包含token并合法,但允许特定路由绕过验证
app.use((req, res, next) => {
  const publicRoutes = ["/login"]; // 允许特定路由绕过验证
  const routeNeedsAuth = !publicRoutes.includes(req.path);
  if (routeNeedsAuth) {
    authenticateToken(req, res, next);
  } else {
    next();
  }
});