node服务生成和验证JWToken

# 实现思路

  • 引入 jsonwebtoken 包,这个包用来生成和解密 jwt

  • 写一个生成 jwt 的方法,这个方法主要用到登录的接口里,然后将生成的 jwt 返回给前端,让前端在每个请求的 header 里面携带 jwt 信息,这里就不做短期 token 和长期 token 了,直接返回一个有效期一天的 token

/** 生成 JWT 的方法 */
export const generateJWToken = (userInfo) => {
  const { user_id, user_type, score } = userInfo;
  const JWToken = jwt.sign({ user_id, user_type, score }, CRYPTO_KEY, {
    expiresIn: '1d',
  });
  return JWToken;
};
  • 写一个接口的路由拦截,这里通过解析请求的 header 信息里面的 authorization,拿到 JWToken 后进行解密,之后根据解密信息的 score 和接口所需要的最小 score,判断用户是否有请求接口的权限
/** 验证 JWT 并且对用户权限进行校验 */
export const authenticateAndAuthorize = (minScore = 0) => {
  return (req, res, next) => {
    const authHeader = req.headers.authorization;
    if (authHeader) {
      const JWToken = authHeader.split(' ')[1];
      jwt.verify(JWToken, CRYPTO_KEY, (err, user) => {
        if (err) {
          return res.send({
            error: `令牌已经无效!`,
          });
        }
        req.user = user;
        const { score } = req.user;
        const hasAuth = Number(score) >= Number(minScore);
        if (hasAuth) {
          next();
        } else {
          return res.send({
            noAuth: true,
            error: `积分不够!该接口需要${minScore}积分呀`,
            minScore,
          });
        }
      });
    } else {
      res.send({
        error: `登录状态已失效,请重新登录!`,
      });
    }
  };
};

# 使用示例

  • 在接口的路由处添加拦截,设置最小要求的积分数量
router.post(
  '/getUserList',
  authenticateAndAuthorize(10000),
  async (req, res) => {
    log(JSON.stringify(req.body));
    const queryUserSql = `select * from ${DB_NAME}.user_table where user_type <> "superAdmin" `;
    try {
      const list = await runSql(queryUserSql);
      res.send(list);
    } catch (e) {
      res.send({
        error: '查询接口报错!',
      });
    }
  },
);