☰
前后端的身份认证
2026/10/9 2:30:26 网站建设 项目流程

一.session

cookie(会员卡):

  1. 不超过4KB
  2. 多个键值对形式
  3. 域名独立
  4. 自动发送 未过期的
  5. 不安全

二.JWT

1.密钥

密钥是什么

密钥就是一个保密的字符串,类似于你的银行卡密码,但通常更长更随机。

在 JWT 的签名算法(如 HS256)中,密钥的作用是:

  • 服务端用它对 header 和 payload 进行签名,生成第三段 signature
  • 服务端再用同一个密钥去验证签名,判断 token 是否被篡改

密钥只有服务端知道,客户端永远不应该拿到它。


密钥怎么来的

有三种常见来源:

1. 自己手动生成(开发测试用)

bash

bash

# 可以用 Node.js 内置的 crypto 模块生成 node -e "console.log(require('crypto').randomBytes(32).toString('hex'))" # 输出类似:a1b2c3d4e5f6...(64位十六进制字符)

这条命令会生成一个256 位的随机密钥,适合 HS256 算法。

2. 环境变量配置(推荐用于生产)

javascript

javascript

// .env 文件 JWT_SECRET=my_super_secret_key_2024_x9k2m7 // Node 代码中读取 const jwtSecret = process.env.JWT_SECRET;
3. 在线密钥生成器

搜索 "jwt secret generator",网站会自动生成高强度密钥。但注意:不要在不可信的网站上输入你自己的密钥。


密钥的关键注意事项

要点

说明

长度​

HS256 至少需要 256 位(32字节),HS512 需要 512 位(64字节)。太短容易被暴力破解。

随机性​

必须用加密安全的随机数生成器(如crypto.randomBytes),不要自己随便打一串字母。

存储​

永远放在环境变量或密钥管理服务(如 AWS KMS、腾讯云凭据管理系统)中,绝不硬编码在代码里。

定期轮换​

生产环境建议每 90 天更换一次密钥,旧密钥可保留一段时间用于验证未过期的老 token。

泄露后果​

密钥泄露 = 任何人都能用你的密钥签发任意身份的 token,等于整个认证系统崩溃。


一段完整示例(Node.js)

javascript

javascript

const jwt = require('jsonwebtoken'); // 1. 生成密钥(实际项目中从环境变量读取) const SECRET_KEY = process.env.JWT_SECRET || 'fallback_dev_key_only'; // 2. 签发 token const token = jwt.sign( { userId: 123, role: 'admin' }, SECRET_KEY, { expiresIn: '24h' } ); // 3. 验证 token try { const decoded = jwt.verify(token, SECRET_KEY); console.log('验证通过,用户ID:', decoded.userId); } catch (err) { console.log('验证失败,token 无效或被篡改'); }

一句话总结

密钥就是一个只有服务端知道的随机字符串,用来给 JWT 签名和验签。你可以用crypto.randomBytes生成它,通过环境变量管理它,绝不能让它离开服务器。

2.JWT身份认证完整流程

好的,下面是 JWT 身份认证的完整流程,并深入到底层生成与验证的细节。


一、整体流程(高视角)

┌─────────┐ ┌──────────────┐ │ 客户端 │ │ 服务端 │ │ (浏览器) │ │ (Node/Java等)│ └────┬────┘ └──────┬───────┘ │ │ │ 1. 登录 (账号+密码) │ │─────────────────────>│ │ │ 2. 验证账号密码 │ │ 3. 生成 JWT │ │ (header.payload.signature) │ 4. 返回 JWT │ │<─────────────────────│ │ │ │ 5. 存储 JWT │ │ (localStorage/cookie) │ │ │ │ 6. 请求API (带JWT) │ │─────────────────────>│ │ │ 7. 提取 JWT │ │ 8. 验证签名 & 过期 │ │ 9. 解析 payload │ 10. 返回资源/数据 │ │<─────────────────────│

二、底层逻辑:JWT 是如何生成的?

JWT 由三部分组成,用.连接:header.payload.signature

1. Header(头部)

{ "alg": "HS256", // 签名算法,常用 HS256 (HMAC-SHA256) 或 RS256 "typ": "JWT" // 令牌类型 }
  • 将 JSON 进行Base64URL 编码(不是普通 Base64,因为 URL 中+/=有特殊含义,Base64URL 将其替换为-_并去掉=)。
  • 得到第一部分字符串,例如:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

2. Payload(载荷)

{ "sub": "1234567890", // subject,通常是用户ID "name": "John Doe", "iat": 1516239022, // issued at,签发时间戳 "exp": 1516242622 // expiration time,过期时间戳 }
  • 同样进行Base64URL 编码。
  • 注意:Payload 是明文编码,不是加密!任何人只要解码 Base64 就能看到里面的内容,所以绝不要放密码等敏感信息。

3. Signature(签名)

签名是对前两部分的完整性保护,防止篡改。

签名生成公式(以 HS256 为例):

signature = HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret_key )
  • 将前两部分的 Base64 字符串用.拼接。
  • 用服务端持有的密钥(secret_key)对该字符串进行 HMAC-SHA256 运算。
  • 结果再进行 Base64URL 编码,得到第三段。

最终 JWT 示例:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ. SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

三、底层逻辑:JWT 是如何验证的?

当服务端收到客户端的 JWT 时,执行以下步骤:

  1. 分割:用.分割得到 header、payload、signature 三部分。
  2. 解码 header:Base64URL 解码 header,获取签名算法(如 HS256)。
  3. 重新计算签名:使用与生成时完全相同的密钥和算法,对base64(header) + "." + base64(payload)重新计算签名。
  4. 比较签名:将新计算的签名与 JWT 第三段进行比较。
    • 相同:说明内容没有被篡改(因为密钥只有服务端知道,攻击者无法伪造合法签名)。
    • 不同:直接拒绝,返回 401。
  5. 检查有效期:解码 payload,取出exp(过期时间),与当前时间对比。如果已过期则拒绝。
  6. 可选检查:检查iss(签发者)、aud(受众)等声明是否符合预期。

注意:验证过程中不会向数据库发起查询(除非你需要检查用户是否被禁用等额外逻辑),这就是 JWT 无状态的本质。


四、关键安全要点

要素

说明

密钥保护​

密钥是核心秘密,必须存储在服务端环境变量或密钥管理服务中,绝不在客户端出现。

签名算法选择​

生产环境推荐RS256(非对称加密),公钥公开,私钥保密,适合多服务间验证。HS256 是对称加密,密钥泄露风险更高。

过期时间​

必须设置exp,通常较短(15分钟~2小时),配合刷新令牌(Refresh Token)使用。

Payload 不加密​

即使有签名,payload 仍是明文,敏感信息(密码、信用卡)不能放进去。

HTTPS 强制​

所有传输必须在 HTTPS 下进行,防止中间人截获 JWT。

防重放攻击​

可使用jti(唯一标识)结合黑名单机制,防止同一 JWT 被多次使用(视安全等级而定)。


五、一句话总结

JWT 认证的本质是:服务端用密钥对用户身份信息进行签名,生成一个自包含的令牌;客户端每次请求都带上它,服务端通过重新计算签名来验证令牌的真实性和完整性,从而确认用户身份,全程无需查询会话存储。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询