JWT 认证
DNS-Go 使用 JWT(JSON Web Token)进行用户认证,提供安全、无状态的认证机制。
什么是 JWT
JWT 是一种开放标准(RFC 7519),用于在网络应用环境间安全地传输信息。JWT 由三部分组成:
Header.Payload.Signature- Header:令牌类型和签名算法
- Payload:声明信息(用户ID、角色、过期时间等)
- Signature:签名,用于验证令牌真实性
DNS-Go 中的 JWT
认证流程
┌──────────┐ ┌──────────┐ ┌──────────┐
│ 客户端 │───1.登录请求───────▶│ DNS-Go │───2.验证账号密码────▶│ 数据库 │
│ │ │ 服务端 │◀──3.返回用户信息─────│ │
│ │◀──4.返回 JWT───────│ │ │ │
│ │ │ │ │ │
│ │───5.携带 JWT 请求──▶│ │───6.验证 JWT───────▶│ │
│ │◀──7.返回数据───────│ │◀──8.JWT 有效───────│ │
└──────────┘ └──────────┘ └──────────┘流程说明:
- 客户端发送登录请求(用户名、密码)
- 服务端验证账号密码
- 数据库返回用户信息
- 服务端生成 JWT 并返回给客户端
- 客户端后续请求携带 JWT(Authorization 头部)
- 服务端验证 JWT 有效性
- 返回请求的数据
Token 结构
DNS-Go 的 JWT Payload 包含以下信息:
json
{
"user_id": 1,
"username": "admin",
"role": "super_admin",
"iat": 1705312225,
"exp": 1705398625
}| 字段 | 说明 |
|---|---|
| user_id | 用户唯一标识 |
| username | 用户名 |
| role | 用户角色 |
| iat | 签发时间(Issued At) |
| exp | 过期时间(Expiration) |
配置说明
JWT 配置项
在配置文件的 [jwt] 段配置 JWT 参数:
toml
[jwt]
# JWT 密钥(必须修改!)
# 用于签名和验证 Token,泄露会导致安全风险
secret_key = "your_jwt_secret_key_min_32_chars"
# Token 过期时间(小时)
# 建议:24(1天)到 168(7天)之间
expires_in = 24安全建议
⚠️ 重要:生产环境必须修改 secret_key!
- 使用至少 32 位的随机字符串
- 包含大小写字母、数字、特殊字符
- 定期更换密钥(建议 90 天)
- 不要将密钥硬编码在代码中
- 不要将密钥提交到版本控制
生成安全密钥的方法:
bash
# 使用 openssl 生成
openssl rand -base64 32
# 使用 Python 生成
python -c "import secrets; print(secrets.token_hex(32))"
# 使用 pwgen 生成
pwgen -s 32 1API 使用
登录获取 Token
bash
POST /api/auth/login
Content-Type: application/json
{
"username": "admin",
"password": "admin123"
}成功响应:
json
{
"code": 200,
"message": "登录成功",
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expires_in": 86400,
"user": {
"id": 1,
"username": "admin",
"nickname": "管理员",
"role": "super_admin"
}
}
}使用 Token 访问 API
在 HTTP 请求的 Authorization 头部携带 Token:
bash
GET /api/domain/list
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...格式说明:
- 头部名称:
Authorization - 值格式:
Bearer+ Token(注意 Bearer 后面有空格)
Token 刷新
当前 Token 即将过期时,可以刷新获取新 Token:
bash
POST /api/auth/refresh
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...响应:
json
{
"code": 200,
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expires_in": 86400
}
}登出
bash
POST /api/auth/logout
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...错误处理
Token 过期
json
{
"code": 401,
"message": "Token 已过期"
}处理方式:
- 刷新 Token(如支持)
- 重新登录获取新 Token
Token 无效
json
{
"code": 401,
"message": "Token 无效"
}可能原因:
- Token 格式错误
- Token 被篡改
- 密钥已更换
权限不足
json
{
"code": 403,
"message": "权限不足"
}处理方式:
- 确认用户角色是否有该权限
- 联系管理员调整权限
前端集成
存储 Token
localStorage(推荐用于 SPA):
javascript
// 登录成功后存储
localStorage.setItem('token', response.data.token);
// 请求时获取
token = localStorage.getItem('token');sessionStorage(浏览器关闭后失效):
javascript
sessionStorage.setItem('token', response.data.token);⚠️ 安全注意:
- 不要将 Token 存储在 cookie 中(防止 CSRF)
- 敏感操作前验证 Token 有效性
- 登出时清除存储的 Token
自动添加 Token
使用 Axios 拦截器自动添加 Token:
javascript
import axios from 'axios';
// 请求拦截器
axios.interceptors.request.use(
(config) => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
// 响应拦截器处理 Token 过期
axios.interceptors.response.use(
(response) => response,
(error) => {
if (error.response?.status === 401) {
// Token 过期,清除并跳转登录
localStorage.removeItem('token');
window.location.href = '/login';
}
return Promise.reject(error);
}
);安全考虑
Token 安全
使用 HTTPS
- 生产环境必须使用 HTTPS
- 防止 Token 在传输过程中被截获
合理设置过期时间
- 过期时间太短:用户体验差,频繁登录
- 过期时间太长:安全风险增加
- 建议:24 小时
Token 刷新机制
- 支持自动刷新延长会话
- 长期不操作自动失效
单点登录限制
- 可选:限制同一账号同时登录的设备数
- 新登录踢掉旧会话
密钥安全
密钥生成
- 使用加密安全的随机数生成器
- 避免使用可猜测的字符串
密钥存储
- 存储在配置文件或环境变量
- 不要硬编码在代码中
- 生产环境使用密钥管理服务(KMS)
密钥轮换
- 定期更换密钥
- 更换后旧 Token 失效,需要重新登录
常见问题
Q: Token 过期时间在哪里配置?
在配置文件的 [jwt] 段:
toml
[jwt]
secret_key = "your_secret_key"
expires_in = 24 # 单位:小时Q: 如何使所有 Token 失效?
更换 secret_key 后,所有现有 Token 都会失效:
toml
# 修改前
secret_key = "old_secret_key"
# 修改后
secret_key = "new_secret_key"重启服务后,所有用户需要重新登录。
Q: 可以实现记住我吗?
可以,通过调整 expires_in 实现:
toml
# 记住我:7 天
expires_in = 168
# 普通登录:24 小时
expires_in = 24前端根据用户选择传递不同的过期时间参数。
Q: 支持双因素认证吗?
当前版本暂不支持,计划在后续版本添加 2FA 支持。
Q: 可以查看当前登录的 Token 吗?
服务端不存储 Token 信息,无法查看活跃 Token 列表。 如需强制下线用户,只能更换 secret_key。