Jwt学习记录
JWT 概述
JWT 是一种基于 JSON 的轻量级身份认证令牌,用于在客户端和服务器之间安全传递信息。
session 会在服务器端存储用户状态,这在分布式系统中会带来 Session 共享的麻烦。而 JWT 的核心设计是服务器不存储状态,通过令牌本身携带认证信息,实现无状态认证。
- 服务器签发令牌后,无需保存任何用户数据;
- 客户端后续请求携带令牌,服务器只需验证令牌有效性即可完成认证;
- 任何服务器只要拥有密钥,都能验证令牌
设置令牌刷新机制:access token 作为访问令牌,短期有效,refresh token 作为刷新令牌,长期有效;
jwt 常配合 spring security 和 cookies 来使用
JWT 的组成结构
JWT 令牌是一个字符串,有 Header(头部)、Payload(载荷)、Signature(签名)三个部分组成,格式为 Header.Payload.Signature
- Header:声明令牌类型和签名算法,JSON 格式,经 Base64URL 编码后成为第一部分
- Payload:存储需要传递的用户信息,分为标准声明和自定义声明,Json 格式,经 Base64URL 编码后成为第二部分
标准声明:iss:签发者;exp:过期时间;sub:主题;aud:受众;iat:签发时间;nbf:生效时间
自定义声明:根据业务需求添加,以 json 格式 - Signature:防止令牌被篡改,是 JWT 安全性的核心保障;服务器使用 Header 中指定的算法,结合密钥(secret),对编码后的 Header 和 Payload 进行签名:
1 | signature = HMACSHA256( |
JWT 工作方式
JWT 认证分为令牌签发和令牌验证两个阶段
- 客户端获取令牌
用户提交账号密码到服务器登录接口,服务器验证账号密码成功后,生成 JWT 令牌:
- 创建 Header 算法(指定算法)
- 创建 Payload(包含用户 ID、过期时间)
- 用服务器私有秘钥生成 Signature
- 拼接 3 部分作为 token 返回给客户端
- 客户端收到令牌后,存储在 Cookie 中;后续请求时,通过 HTTP 请求头 Auhorization 携带令牌
Authorization: Bearer token - 服务器验证令牌
服务器从请求头提取 JWT 令牌,拆分出 Header、Payload、Signature 三部分,用相同的密钥和算法重新计算签名。对比计算出的签名和令牌中的 Signature,若一致,令牌未被篡改,检查是否过期,若未过期认证通过,解析 Payload 中的用户信息并处理请求。若不一致,令牌被篡改,认证失败,返回 401 错误
JWT 优点
- 服务器无需存储用户信息,减轻存储压力,适配分布式系统
- 令牌本身携带用户信息,减少服务器查询数据库的次数
- 通过签名防止篡改,payload 尽量别传递敏感信息,因为它只是编码而没有加密
JWT 缺点
- 令牌一旦签发,在有效期内始终有效
- Base64URL 编码可逆向解码,不能存储密码等敏感信息;
- 密钥泄露会导致令牌被伪造。
令牌刷新机制
令牌刷新机制是解决 JWT 等短期访问令牌(Access Token)过期问题 的核心方案,目的是在不重复让用户登录的前提下,安全地延续用户的会话权限,平衡安全性与用户体验。
为了保证 JWT 的安全性,访问令牌必须短期有效。但短期有效会导致用户需要频繁的登录,体验极差。而令牌刷新机制就是为了解决这个问题。
- 访问令牌:
access token,用于访问具体业务接口 - 刷新令牌:
refresh token,仅用于向服务器申请新的访问令牌
工作流程
- 首次登录时,用户输入账号密码登录,后端通过验证后生成访问令牌(用户身份、权限等信息)和刷新令牌(随机字符串、无业务信息,与用户 ID、过期时间绑定,加密存储到后端数据库);后端仅返回访问令牌给前端,刷新令牌不返回前端
- 前端每次调用业务接口时,在请求头中携带访问令牌。后端验证访问令牌的有效性,验证通过则正常返回数据
- 当访问令牌过期,后端返回令牌过期错误,前端补货后自动向后端的刷新接口发送请求(不需要用户操作);后端接收到请求后,验证自身存储的 refresh token,若验证通过,生成新的 access token,返回给前端;若验证失败,返回会话失效,前端引导用户重新登录
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Myskill-blog!