99 lines
3.5 KiB
Markdown
99 lines
3.5 KiB
Markdown
# 8.6 Token 使用说明
|
||
|
||
:::tip 概述
|
||
本文档面向 API 对接方:如何获取令牌、如何携带、如何刷新、如何撤销。令牌为 JWT HS256 双令牌(access 2h + refresh 7d),唯一使用下划线命名的响应。
|
||
:::
|
||
|
||
## 获取令牌(POST /api/login,公开)
|
||
|
||
```sh
|
||
curl -X POST http://127.0.0.1:8000/api/login \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"username":"admin","password":"123456","code":"618618","key":"<captcha-key>"}'
|
||
```
|
||
|
||
```json
|
||
{
|
||
"code": 0, "ok": true, "msg": "操作成功",
|
||
"data": {
|
||
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.…",
|
||
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.…",
|
||
"expires_in": 7200,
|
||
"token_type": "Bearer"
|
||
}
|
||
}
|
||
```
|
||
|
||
::: warning 命名例外
|
||
登录/令牌接口返回 `access_token/refresh_token/expires_in/token_type`(OAuth2 惯例下划线命名)——这是全系统唯一例外,其余接口出入参一律驼峰。
|
||
:::
|
||
|
||
## 携带令牌调用业务接口
|
||
|
||
```sh
|
||
curl http://127.0.0.1:8000/api/user/page?pageNo=1&pageSize=10 \
|
||
-H "Authorization: Bearer <access_token>"
|
||
```
|
||
|
||
兼容细节:Bearer 前缀大小写不敏感、可无前缀直接传 token;个别场景支持查询参数 `?token=`(URL 直传)。
|
||
|
||
## 刷新令牌(POST /api/oauth2/token,公开)
|
||
|
||
access 过期(收到 code=401)时用 refresh_token 轮换新令牌对:
|
||
|
||
```sh
|
||
curl -X POST http://127.0.0.1:8000/api/oauth2/token \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"grant_type":"refresh_token","refresh_token":"<refresh_token>"}'
|
||
```
|
||
|
||
```json
|
||
{ "data": { "access_token": "…", "refresh_token": "…", "expires_in": 7200, "token_type": "Bearer" } }
|
||
```
|
||
|
||
刷新语义:
|
||
|
||
```text
|
||
* 旧 refresh 入黑名单(轮换)——旧 refresh_token 立即作废,必须存新值
|
||
* 旧 access 自然过期(不主动拉黑)
|
||
* 返回同登录格式四字段
|
||
* 兼容密码模式:grant_type=password 或无 refresh_token → 复用登录逻辑
|
||
```
|
||
|
||
## 撤销与校验
|
||
|
||
```text
|
||
GET /api/logout 登出(当前 access jti 拉黑)
|
||
DELETE /api/oauth2/remove/:token 撤销指定令牌(登录可用;解析 jti 入黑名单)
|
||
GET /api/oauth2/check/token 校验令牌有效性(JWT 中间件通过即有效)
|
||
```
|
||
|
||
## 对接方实现要点
|
||
|
||
```text
|
||
1. 存储:access 与 refresh 分开存(内存/localStorage);refresh 泄露=账号风险
|
||
2. 请求:全部业务请求带 Authorization: Bearer <access>
|
||
3. 401 处理:单飞刷新(并发 401 只触发一次 refresh,其余等结果);
|
||
refresh 失败(1008/401)→ 清令牌 → 跳登录
|
||
4. 刷新成功:立即用新令牌对覆盖旧值(旧 refresh 已作废)
|
||
5. 时钟偏移:以 expires_in 倒计时提前刷新(如过期前 60s),减少 401
|
||
6. 登出:调 /api/logout 后清本地——不调的话令牌有效期内仍可用
|
||
```
|
||
|
||
## 令牌状态速查
|
||
|
||
| 状态 | 表现 | 处理 |
|
||
|------|------|------|
|
||
| 有效 | 业务正常 | — |
|
||
| access 过期 | code=401 | refresh 轮换 |
|
||
| refresh 过期/已轮换 | code=1 或 1008 | 重新登录 |
|
||
| 已拉黑(登出/强退) | code=401 | 重新登录(强退的 refresh 也拉黑,无法复活) |
|
||
| 算法/签名无效 | code=401 | 检查是否跨环境混用 jwt.secret |
|
||
|
||
## 安全建议
|
||
|
||
+ HTTPS 传输(令牌明文等价于会话)
|
||
+ refresh_token 泄露面最小化(不入 URL、不入日志——后端已脱敏)
|
||
+ 客户端不持久化 access(内存优先);persist refresh 的场景加密存储
|
||
+ 多端登录场景用在线用户模块管理(forceLogout 双令牌拉黑)
|