灏天阁

Node/Koa2[24]: JWT

· Yin灏

JWT

  • jwt - json web token

  • 用户认证成功之后,server 端返回一个加密的 token 给客户端

  • 客户端后续每次请求都带 token,以示当前的用户身份

模拟登录

routes/user.js

//...
const jwt = require("jsonwebtoken");
const { SECRET } = require("../conf/constants");

//...
const util = require("util");
const verify = util.promisify(jwt.verify);
//...
router.post("/login", async (ctx, next) => {
  const { userName, password } = ctx.request.body;
  let userInfo;
  let token;
  if (userName === "zhangsan" && password === "abc") {
    userInfo = {
      userId: 1,
      userName: "zhangsan",
      nickName: "张三",
      gender: 1,
    };
  }

  // 加密
  if (userInfo) {
    token = jwt.sign(userInfo, SECRET, {
      expiresIn: "1h",
    });
  }

  if (userInfo == null) {
    ctx.body = {
      errnno: -1,
      msg: "登录失败",
    };
    return;
  }

  ctx.body = {
    error: 0,
    data: token,
  };
});
//...
// 获取用户信息
router.get("/getUserInfo", async (ctx, next) => {
  const token = ctx.header.authorization;
  try {
    const payload = await verify(token.split(" ")[1], SECRET);
    ctx.body = {
      errno: 0,
      userInfo: payload,
    };
  } catch (ex) {
    ctx.body = {
      errno: -1,
      msg: "verify token failed",
    };
  }
});

数据加密

  • 安装依赖
npm i koa-jwt --save
npm i jsonwebtoken --save #加密工具
  • 引用

app.js

const { SECRET } = require("./conf/constants");
const jwtKoa = require("koa-jwt");
// 需要在路由注册之前引用
app.use(
  jwtKoa({
    secret: SECRET,
  }).unless({
    path: [/^\/users\/login/], // 自定义那些目录忽略 jwt 验证
  })
);
  • 配置

conf/constants.js

module.exports = {
  SECRET: "UsdU*975_+qwe",
};

jwt vs session

  1. 为了解决:登录 & 存储登录用户的信息

  2. jwt 用户信息加密存储在客户端,不依赖 cookie,可跨域

  3. session 用户信息存储在服务端,依赖 cookie,默认不可跨域

  4. 一般情况下,两者都能满足,大型系统中两者可共用

  5. jwt 更适合于服务节点较多,跨域比较多的系统

  6. session 更适合统一的 web 服务,server 要严格管理用户信息

- Book Lists -