JWT(JSON Web Token)是一种无状态的身份认证技术,核心作用是 "让服务器确认'你是谁'",常用于前后端分离、APP 登录等场景。下面用 "大白话 + 图形 + 思维导图",从 "是什么→怎么用→核心逻辑" 一步步讲明白,小白也能轻松理解。
一、先搞懂:JWT 解决了什么问题?(先看痛点)
在 JWT 出现前,很多系统用 "Session 认证",但有个明显缺点:
比如你用手机登录某 APP,每次点新页面,APP 都要给服务器发请求,服务器得查 "我之前是不是认证过这个用户"------ 这就需要服务器存一份 "用户登录记录"(即 Session),如果有 100 万用户登录,服务器要存 100 万条记录,压力很大。
而 JWT 的核心优势是 "服务器不用存记录":用户登录后,服务器给用户发一个 "加密的身份卡片"(JWT),后续用户再发请求时,只要带上这张 "卡片",服务器只要验证 "卡片是真的、没过期",就知道 "你是谁",不用再查数据库。
二、JWT 长什么样?3 部分组成(图形化拆解)
JWT 本质是一串 "用点(.)连接的字符串",共分 3 段,每段都有明确作用,就像 "身份证的 3 个区域":
bash
# JWT 结构:头部.Header + 载荷.Payload + 签名.Signature eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEsInVzZXJOYW1lIjoi5byg5LiJIiwiZXhwIjoxNzE2MjM5MjAwfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
用表格和图形帮你看懂每一段:
组成部分 | 大白话作用 | 核心内容(小白能懂版) | 是否加密? |
---|---|---|---|
1. 头部(Header) | 告诉服务器 "这张卡片用什么方式加密" | - 声明加密算法(比如 HS256,一种对称加密) - 声明类型(固定是 JWT) | 不加密,只是 Base64 编码(能解密看到内容) |
2. 载荷(Payload) | 存放 "用户的核心身份信息"(比如你是谁) | - 标准字段:过期时间(exp)、签发时间(iat) - 自定义字段:用户 ID、用户名(比如 userId:1,userName: 张三) | 不加密,只是 Base64 编码(能解密看到内容,别存密码! ) |
3. 签名(Signature) | 防止 "卡片被篡改"(最关键的安全保障) | - 计算方式:用 Header 里的算法,把 "Header+Payload + 服务器密钥" 混合加密 - 服务器密钥:只有服务器知道,绝不泄露给用户 | 加密,不可逆(用户无法伪造) |
用 "身份证类比" 理解:
- Header = 身份证上的 "签发机关"(告诉别人这张证是谁发的、用什么标准做的)
- Payload = 身份证上的 "姓名、性别、生日"(你的核心信息,别人能看到)
- Signature = 身份证上的 "防伪水印"(只有发证机关能做,别人改不了,改了就失效)
三、JWT 鉴权完整流程(一步一图)
JWT 工作分 "登录签发 Token" 和 "后续请求验证 Token" 两步,用流程图能直观看到每一步的交互:
stateDiagram-v2
[*] : 初始状态
%% 用户侧状态
state 用户 {
用户_未登录 : 用户未登录(无JWT)
用户_输入凭证 : 输入用户名+密码
用户_存储JWT : 本地存储JWT(如APP缓存)
用户_携带JWT请求 : 请求头携带JWT发起业务请求
用户_接收结果 : 接收服务器返回的业务数据
}
%% 服务器侧状态
state 服务器 {
服务器_接收登录请求 : 接收用户登录请求
服务器_验证凭证 : 向数据库校验用户名密码
服务器_生成JWT : 生成Header/Payload/Signature并拼接JWT
服务器_返回JWT : 向用户返回JWT
服务器_接收业务请求 : 接收带JWT的业务请求
服务器_验证JWT : 1.拆分JWT\n2.重算Signature\n3.对比一致性\n4.检查过期时间
服务器_处理业务 : 处理用户业务请求(如查订单)
服务器_返回结果 : 向用户返回业务处理结果
}
%% 数据库侧状态
state 数据库 {
数据库_存储凭证 : 存储用户账号密码
数据库_校验凭证 : 校验服务器传来的用户名密码
}
%% 状态流转逻辑
[*] --> 用户_未登录
%% 第一步:登录流程(JWT生成)
用户_未登录 --> 用户_输入凭证 : 用户触发登录
用户_输入凭证 --> 服务器_接收登录请求 : 发送登录请求(含用户名+密码)
服务器_接收登录请求 --> 数据库_校验凭证 : 发起凭证校验请求
数据库_校验凭证 --> 服务器_验证凭证 : 返回校验结果(正确/错误)
服务器_验证凭证 --> 服务器_生成JWT : 校验通过(仅正确时流转)
服务器_生成JWT --> 服务器_返回JWT : JWT生成完成
服务器_返回JWT --> 用户_存储JWT : 用户接收JWT
用户_存储JWT --> 用户_携带JWT请求 : 用户触发业务操作(如查订单)
%% 第二步:鉴权流程(JWT验证与业务处理)
用户_携带JWT请求 --> 服务器_接收业务请求 : 发送业务请求(请求头带JWT)
服务器_接收业务请求 --> 服务器_验证JWT : 触发JWT鉴权
服务器_验证JWT --> 服务器_处理业务 : 鉴权通过(Signature一致+未过期)
服务器_处理业务 --> 服务器_返回结果 : 业务处理完成
服务器_返回结果 --> 用户_接收结果 : 用户接收业务数据
用户_接收结果 --> [*] : 流程结束
%% 异常分支(简化)
数据库_校验凭证 --> 用户_未登录 : 校验失败(密码错误等)
服务器_验证JWT --> 用户_未登录 : 鉴权失败(JWT篡改/过期)
关键验证步骤(小白必记):
- 验签名:服务器会用自己的密钥重新算一遍签名,如果和用户带的签名不一样,说明 JWT 被篡改过,直接拒绝。
- 验过期:看 Payload 里的过期时间(exp),如果当前时间超过这个值,说明 JWT 失效,让用户重新登录。
四、JWT 配置 / 使用思维导图(小白可落地)
下面用思维导图拆解 "从准备到实际使用" 的全流程,每个步骤都有具体操作说明:
一、JWT 前期准备(服务器端配置)
1. 选工具/库(不用自己写加密)
- 后端是 Java:用 JJWT 库(常用)
- 后端是 Python:用 PyJWT 库
- 后端是 Node.js:用 jsonwebtoken 库
- 小白重点:不用懂底层加密,调用库的现成方法即可
2. 配置"服务器密钥"(核心安全项)
- 要求:长一点、复杂一点(比如"a1b2c3d4e5!@#$%^&*")
- 注意:密钥只存在服务器,绝对不能发给用户/前端!(泄露了别人就能伪造 JWT)
3. 配置"过期时间"(Payload 里的 exp)
- 短期场景(比如APP):设 2小时(过期后让用户重新登录,更安全)
- 长期场景(比如后台管理系统):设 8小时(和上班时间匹配)
- 避免:设太长(比如1年),万一 JWT 丢了,别人能冒用很久
二、JWT 核心流程:登录签发 Token
1. 接收用户登录信息
- 前端传"用户名+密码"(用 HTTPS 传输,防密码被偷)
- 服务器验证"用户名密码是否正确"(查数据库)
2. 生成 JWT(调用工具库)
- 组装 Header:{"alg":"HS256","typ":"JWT"}(HS256是常用对称算法)
- 组装 Payload:{"userId":123,"userName":"张三","exp":1716239200}(exp是过期时间的时间戳)
- 生成 Signature:用"服务器密钥"+ HS256 算法,对 Header+Payload 加密
- 拼接成 JWT:Header编码.Base64 + "." + Payload编码.Base64 + "." + Signature
3. 返回 JWT 给前端
- 前端存 JWT:APP 存到本地存储,网页存到 localStorage/sessionStorage
三、JWT 核心流程:请求验证 Token
1. 前端携带 JWT 发请求
- 在请求头里加"Authorization: Bearer JWT字符串"(固定格式)
- 例:Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
2. 服务器验证 JWT(调用工具库)
- 步骤1:拆分 JWT 为 Header、Payload、Signature
- 步骤2:验证 Signature:用服务器密钥重新计算,对比是否一致(不一致则拒绝)
- 步骤3:验证过期时间:看 Payload 的 exp,过期则返回"请重新登录"
- 步骤4:验证通过:从 Payload 里取用户ID(比如 userId:123),查询用户数据,返回请求结果
四、JWT 注意事项(小白避坑)
1. 安全问题
- 别在 Payload 里存敏感信息(比如密码、手机号),因为 Payload 只是 Base64 编码,能解密看到
- 必须用 HTTPS 传输 JWT,防止传输过程中被偷
- 服务器密钥要定期更换,防止密钥泄露
2. 过期问题
- JWT 一旦签发,服务器没法主动"作废"(比如用户注销登录),只能等过期
- 解决办法:重要场景(比如支付),可以在服务器存"黑名单",注销的 JWT 加入黑名单,验证时查黑名单
3. 性能问题
- JWT 字符串别太长(比如 Payload 别塞太多信息),否则每次请求都要传一大串字符,影响速度