Node基于JWT实现Token验证、登录验证

5/6/2021 NodejwtToken

# 文章目录

本文介绍怎么使用 jsonwebtoken 库实现基于非对称加密算法的 token 认证。
文末有完整源码。

# 一、Token 的组成

JWT 生成的 Token 由三部分组成:

header

  • alg:采用的加密算法,默认是 HMAC SHA256(HS256),采用同一个密钥进行
    加密和解密;
  • typ:JWT,固定值,通常都写成 JWT 即可;
  • 会通过 base64Url 算法进行编码;

payload

  • 携带的数据,比如我们可以将用户的 id 和 name 放到 payload 中;
  • 默认也会携带 iat(issued at),令牌的签发时间;
  • 我们也可以设置过期时间:exp(expiration time);
  • 会通过 base64Url 算法进行编码

signature

  • 设置一个 secretKey,通过将前两个的结果合并后进行 HMACSHA256 的算法;
  • HMACSHA256(base64Url(header)+.+base64Url(payload), secretKey);
  • 但是如果 secretKey 暴露是一件非常危险的事情,因为之后就可以模拟颁发 token,也可以解密 token;

# 二、生成私钥和公钥

以下操作需要 openssl协议支持,mac系统自带,windows使用Git Bash Here

# 3.1 生成私钥

会在当前目录生成一个 private.key的私钥
genrsa \-out private.key

# 3.2 根据私钥生成公钥

会在当前目录生成一个 public.key的私钥
rsa \-in private.key \-pubout \-out public.key

# 三、实现基于非对称加密的 token 认证

完整源码:
index.js

const Koa = require("koa");
const Router = require("koa-router");
const jwt = require("jsonwebtoken");
const fs = require("fs");

const app = new Koa();
const testRouter = new Router();

// 注意:在项目中的任何一个地方的相对路径,都是相对于 process.cwd
const PRIVATE_KEY = fs.readFileSync("./keys/private.key");
const PUBLIC_KEY = fs.readFileSync("./keys/public.key");

// 登录接口
testRouter.post("/register", (ctx, next) => {
  const user = { id: 110, name: "why" };
  // 这里能拿到 颁发的token
  const token = jwt.sign(user, PRIVATE_KEY, {
    expiresIn: 120, //过期时间 单位:s
    // 指定加密算法 RS256=>非对称加密(安全,速度不及HS256) HS256=>对称加密(不及RS256安全,但速度快)默认
    algorithm: "RS256",
  });
  ctx.body = token;
});
// 验证接口
testRouter.post("/login", (ctx, next) => {
  const authorization = ctx.headers.authorization;
  const token = authorization.replace("Bearer ", "");

  console.log("token: ", token);

  try {
    // 验证token
    const result = jwt.verify(token, PUBLIC_KEY, {
      // 指定了什么加密,则用什么解密,可以指定多个解密算法
      algorithms: ["RS256"],
    });
    // 验证不通过或失败会抛出异常
    ctx.body = `验证结果:${JSON.stringify(result)}`;
  } catch (error) {
    ctx.body = `Token无效:${error}`;
  }
});

app.use(testRouter.routes());
app.use(testRouter.allowedMethods());

app.listen(8000, () => {
  console.log("start");
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

private.key

-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAvYySUOyU4OKAgN0sF7XSSCnNXUMAPuI3wFKRYowl34eaAgBm
cXpqNmhucwmWeyv6hh2mddGw/dK7EqJYDd3NSyFKAGXVGj4IMUqpRQFcL8WICTKL
fY2S1aO+MHAgUZZtVjvk6e//ygv+/LOJfBlV8DbxCaiBpjiCUlIC01bg2lOhY8BP
9JZyqjD+Nricz50YLRZjltCepJu2meSOEdD0siP6xoKbML043L0xr3/sqTKt8Hz+
yuqw5lgIxH5TDKYzM+8Rz76lyEy15SQ/V9QTXmnQ6ZTH9lJCNA6i7rNVe5OfvBkb
f/vLdy91Hmrj9/Om4BSy92s4cKkpiWZIW19pSwIDAQABAoIBAAYrThPOL2ZGWPJY
wHehFk/89E8lwBtL146t4Ud40j69Nhj8lFj7J/vPWFDsLfaiTswQqPtKsN0B/86y
c/U3k9fvJG5w4gexnyijinDRg4OWhT/vYjTa572GT8lZzON65uIYnvGyOvwDefAV
k9LzLCXeU+gBkP6s9ijhvG/OcxEH+1ATCSI3b/DNpKCEd1YG0y9mZYKxzqRDJLL2
4OzdM+n6tugYNZy4smE0AQMpKsNtyp2yhyEv4CcZSIQ+DYxnCgtHYsIRudHyDlaP
3X5LyBoCSKsS1YT+nJiYhGowSgmXee6uo2ny0Nw+J5WII+uv/cCazxrOTZMBQxHO
3SiSsmkCgYEA+8jeDUQsAs1SiTHrD23R2MhHH4wS2jB0EqCkdeuP8pajPG1ZKpXX
b9+WuF7e1a1K5fZYmGgBUOd30pWG0A0s/CgZ+5Dti5KYrRsq0hBB0fvV/8op9XJx
2jVKnaIQVIyKfw+S5BIGLmQId9HS3yzhSOOmAXQBzqykqlQ6zXaN21cCgYEAwLj3
epZsVqFFBYCH9X/HgGq9oj7pSzn4t8OIW97yiugt8b0+W7rn0DO2eHR+Sx7iX/tx
8+w2YuEPEKytmvJw4VCNMPR3lOiLy0Pjk6qNxFnFEDWuM6GBZoexiVr0WWbfaxEI
ELaLD1NcTG3fQWxjNPz3EdCI7rWijXtEztrBHS0CgYEAlzVUlWcBf1VLYfVGk2eC
hMwSWpHGqJ48twseeWrUcf2hXqLUz8xZK2h9nY/sByshNeWx4yVi1PGNdjwyUDP5
dh2nLPsmjZGmex87ohf9T1wMcqc4d50ZXtBuVSiE4iHc8t2pe6qPZ8DPjRXHrBvJ
1/pPMcQ3aaUo5tnazpWKL9UCgYA/WQ1P6D34Q85SPqtyEOxc07k9qXw50/ZjQQyD
VkdXTXY8rb3fnRIxp63k7jXNL3utnRMZ4J0H535yNrBh7CsahMXEP7dG5SF+UPRv
R3KOBgv2hg6avg2wzA2ZXqJO+Lebk9+Yzsfq47XFEaB++sepVTVJT8iS3nVuGATI
EbPEiQKBgQCaW9oaP9sZkmOcVSRi9r7PdrlLggBsrfOCQNfMAzuEDV3T9J9+1pDR
qZeo+Gue/rYeWtmyhiGchM4AeJkhicMdYfuDwliZxbeBptzqcbXSIAifTq9X4e45
FgaF7aEWUnqRWjSoMFRjN+B5MBrrdOnAaaK+cAGa9SCUU4/hgPUgbA==
-----END RSA PRIVATE KEY-----
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

public.key

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvYySUOyU4OKAgN0sF7XS
SCnNXUMAPuI3wFKRYowl34eaAgBmcXpqNmhucwmWeyv6hh2mddGw/dK7EqJYDd3N
SyFKAGXVGj4IMUqpRQFcL8WICTKLfY2S1aO+MHAgUZZtVjvk6e//ygv+/LOJfBlV
8DbxCaiBpjiCUlIC01bg2lOhY8BP9JZyqjD+Nricz50YLRZjltCepJu2meSOEdD0
siP6xoKbML043L0xr3/sqTKt8Hz+yuqw5lgIxH5TDKYzM+8Rz76lyEy15SQ/V9QT
XmnQ6ZTH9lJCNA6i7rNVe5OfvBkbf/vLdy91Hmrj9/Om4BSy92s4cKkpiWZIW19p
SwIDAQAB
-----END PUBLIC KEY-----
1
2
3
4
5
6
7
8
9
最后更新于: 2021年9月15日星期三晚上10点10分
Faster Than Light
Andreas Waldetoft / Mia Stegmar