JWT(JSON Web Token)是一种紧凑的 token 格式,常用于在客户端和服务端之间传递已签名的身份信息。用户登录成功后拿到 JWT,后续请求携带它,服务端便可以验证“是谁在发请求”。
JWT 的结构
一个 JWT 通常由三段组成,中间用 . 分隔:
| 部分 | 内容 | 作用 |
|---|
| Header | token 类型、签名算法 | 告诉验证方如何处理 token |
| Payload | user_id、角色、过期时间等声明 | 携带身份信息 |
| Signature | 对前两段计算出的签名 | 检测内容是否被篡改 |
Header 和 Payload 只是 Base64URL 编码,不是加密。拿到 token 的人通常可以读取其中内容,因此不能把密码、API Key 或其他秘密放进 Payload。
登录和请求过程
客户端通常通过 HTTP 请求头发送 token:
Authorization: Bearer <jwt>
Bearer 的含义是“持有者凭证”:谁拿到它,谁就可能以该用户身份调用接口。因此客户端必须妥善保存 token,并全程使用 HTTPS。
签名能保证什么
签名可以帮助服务端确认:
- token 由持有正确密钥的一方签发;
- Header 和 Payload 在签发后没有被修改。
签名不能隐藏 Payload,也不能在 token 泄露后阻止攻击者使用它。实际系统还需要较短的过期时间、安全存储、HTTPS,以及必要时的撤销或刷新机制。
常见字段
JWT 中的字段通常称为 claims(声明):
{
"user_id": 1,
"username": "admin",
"role": "root",
"exp": 1781618346
}
| 字段 | 含义 |
|---|
user_id | 当前用户的唯一标识 |
username | 用户名 |
role | 用于授权判断的角色 |
exp | token 的过期时间(Unix 时间戳) |
**鉴权(authentication)**回答“你是谁”,**授权(authorization)**回答“你能做什么”。JWT 可以携带身份和角色,但服务端仍必须根据资源归属、角色和可见性规则进行授权,不能因为签名有效就允许所有操作。
RakuLLApp 的实现
RakuLLApp 当前使用 HS256:
user_manager 使用 JWT_SECRET 签发 JWT;
- 其他服务使用同一个
JWT_SECRET 验证签名;
- Controller 从 token 中取得用户和角色,再执行权限及可见性判断;
- token 会作为
Bearer 凭证在需要鉴权的调用中传播。
HS256 使用同一个密钥签名和验证。这种方式配置简单,但也意味着每个持有 JWT_SECRET 的服务理论上都能签发 token,所以密钥只能放在安全配置中,不能提交到仓库或发送给客户端。
修改 Payload 后重新编码并不会得到有效 JWT,因为签名将不再匹配。反过来,能读取 Payload 也不代表能伪造签名。
关于本项目的 token 传播、匿名访问和权限规则,继续阅读 鉴权与权限。