多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

前后端的身份认证

前后端的身份认证 一.sessioncookie会员卡不超过4KB多个键值对形式域名独立自动发送 未过期的不安全二.JWT1.密钥密钥是什么密钥就是一个保密的字符串类似于你的银行卡密码但通常更长更随机。在 JWT 的签名算法如 HS256中密钥的作用是服务端用它对 header 和 payload 进行签名生成第三段 signature服务端再用同一个密钥去验证签名判断 token 是否被篡改密钥只有服务端知道客户端永远不应该拿到它。密钥怎么来的有三种常见来源1. 自己手动生成开发测试用bashbash# 可以用 Node.js 内置的 crypto 模块生成 node -e console.log(require(crypto).randomBytes(32).toString(hex)) # 输出类似a1b2c3d4e5f6...64位十六进制字符这条命令会生成一个256 位的随机密钥适合 HS256 算法。2. 环境变量配置推荐用于生产javascriptjavascript// .env 文件 JWT_SECRETmy_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.jsjavascriptjavascriptconst 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.signature1. Header头部{ alg: HS256, // 签名算法常用 HS256 (HMAC-SHA256) 或 RS256 typ: JWT // 令牌类型 }将 JSON 进行Base64URL 编码不是普通 Base64因为 URL 中/有特殊含义Base64URL 将其替换为-_并去掉。得到第一部分字符串例如eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ92. 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 时执行以下步骤分割用.分割得到 header、payload、signature 三部分。解码 headerBase64URL 解码 header获取签名算法如 HS256。重新计算签名使用与生成时完全相同的密钥和算法对base64(header) . base64(payload)重新计算签名。比较签名将新计算的签名与 JWT 第三段进行比较。相同说明内容没有被篡改因为密钥只有服务端知道攻击者无法伪造合法签名。不同直接拒绝返回 401。检查有效期解码 payload取出exp过期时间与当前时间对比。如果已过期则拒绝。可选检查检查iss签发者、aud受众等声明是否符合预期。注意验证过程中不会向数据库发起查询除非你需要检查用户是否被禁用等额外逻辑这就是 JWT 无状态的本质。四、关键安全要点要素说明密钥保护​密钥是核心秘密必须存储在服务端环境变量或密钥管理服务中绝不在客户端出现。签名算法选择​生产环境推荐RS256非对称加密公钥公开私钥保密适合多服务间验证。HS256 是对称加密密钥泄露风险更高。过期时间​必须设置exp通常较短15分钟~2小时配合刷新令牌Refresh Token使用。Payload 不加密​即使有签名payload 仍是明文敏感信息密码、信用卡不能放进去。HTTPS 强制​所有传输必须在 HTTPS 下进行防止中间人截获 JWT。防重放攻击​可使用jti唯一标识结合黑名单机制防止同一 JWT 被多次使用视安全等级而定。五、一句话总结JWT 认证的本质是服务端用密钥对用户身份信息进行签名生成一个自包含的令牌客户端每次请求都带上它服务端通过重新计算签名来验证令牌的真实性和完整性从而确认用户身份全程无需查询会话存储。
返回列表