实现了滑动过期(Sliding Expiration)Token机制,确保用户在活跃使用系统时不会遇到token超时问题。
在 config.ini 中添加以下配置:
# 后台管理Token配置
ADMIN_TOKEN_EXPIRE_MINUTES=10 # 访问token有效期(分钟)
ADMIN_REFRESH_TOKEN_EXPIRE_HOURS=24 # 刷新token有效期(小时)
用户请求API → 验证token → 检查是否需要刷新 → 生成新token → 返回响应 + 新token
X-New-Tokenfrom app.utils.auth_decorator import get_current_user_with_sliding_expiration
@router.get("/my-api")
async def my_api(
user_info: dict = Depends(get_current_user_with_sliding_expiration)
):
user = user_info["user"] # 当前用户对象
new_token = user_info["new_token"] # 新token(可能为None)
# 构造响应
response_data = {"message": "success", "data": {...}}
# 如果token被刷新,添加到响应中
if new_token:
response_data["token_refreshed"] = True
response_data["new_token"] = new_token
return response_data
from app.services.auth_service import AuthService
@router.get("/manual-api")
async def manual_api(
credentials: HTTPAuthorizationCredentials = Depends(security),
db: AsyncSession = Depends(get_db_connection)
):
auth_service = AuthService(db)
user, new_token = await auth_service.get_current_user(credentials.credentials)
if not user:
return {"code": 401, "message": "无效的访问令牌"}
response_data = {"code": 0, "message": "success", "data": {...}}
if new_token:
response_data["token_refreshed"] = True
response_data["new_token"] = new_token
return response_data
在主应用文件中添加:
from app.middleware.token_refresh_middleware import TokenRefreshMiddleware
app.add_middleware(
TokenRefreshMiddleware,
exclude_paths=[
"/auth/login",
"/auth/captcha",
"/docs",
"/openapi.json"
]
)
class ApiClient {
constructor() {
this.token = localStorage.getItem('access_token');
}
async request(url, options = {}) {
const headers = {
'Authorization': `Bearer ${this.token}`,
...options.headers
};
const response = await fetch(url, { ...options, headers });
const data = await response.json();
// 检查token刷新
if (data.token_refreshed && data.new_token) {
this.token = data.new_token;
localStorage.setItem('access_token', data.new_token);
console.log('Token已自动刷新');
}
// 也可以检查响应头
const newToken = response.headers.get('X-New-Token');
if (newToken) {
this.token = newToken;
localStorage.setItem('access_token', newToken);
console.log('Token已通过响应头刷新');
}
return data;
}
}
// axios拦截器
axios.interceptors.response.use(
response => {
// 检查响应数据中的token刷新
if (response.data?.token_refreshed && response.data?.new_token) {
const newToken = response.data.new_token;
localStorage.setItem('access_token', newToken);
axios.defaults.headers.common['Authorization'] = `Bearer ${newToken}`;
console.log('Token已刷新');
}
// 检查响应头中的token刷新
const headerToken = response.headers['x-new-token'];
if (headerToken) {
localStorage.setItem('access_token', headerToken);
axios.defaults.headers.common['Authorization'] = `Bearer ${headerToken}`;
console.log('Token已通过响应头刷新');
}
return response;
},
error => {
if (error.response?.status === 401) {
// token完全过期,跳转登录
router.push('/login');
}
return Promise.reject(error);
}
);
{
"code": 0,
"message": "success",
"data": {...}
}
{
"code": 0,
"message": "success",
"data": {...},
"token_refreshed": true,
"new_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
}
响应头:
X-New-Token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...
X-Token-Refreshed: true
cd LQAdminPlatform
python test_sliding_token.py
🚀 开始测试滑动过期Token机制
============================================================
🧪 测试4: 配置加载
✅ 后台管理Token过期时间: 10 分钟
✅ 通用Token过期时间: 30 分钟
✅ 刷新Token过期时间: 24 小时
🎯 实际使用的过期时间: 10 分钟
🧪 测试1: Token创建
✅ Token创建成功: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
✅ Token验证成功: 用户=testuser
过期时间: 2026-01-30 04:06:08+00:00
🎉 所有测试完成!
# 1. 登录获取token
curl -X POST "http://localhost:8000/auth/login" \
-H "Content-Type: application/json" \
-d '{"username": "admin", "password": "password"}'
# 2. 使用token调用API(支持滑动过期)
curl -X GET "http://localhost:8000/system/info" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
# 3. 检查响应中的token_refreshed字段
{
"code": 0,
"message": "获取系统信息成功",
"data": {
"system_name": "LQ后台管理系统",
"version": "1.0.0",
"current_time": "2026-01-30T11:56:08.325863+00:00",
"current_user": {
"id": "user123",
"username": "admin",
"email": "admin@example.com",
"is_superuser": true
}
},
"token_refreshed": true,
"new_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
}
INFO - Token已刷新,用户: admin
INFO - 系统信息API - Token已刷新,用户: admin
from app.services.jwt_token import verify_and_refresh_token
payload, new_token = verify_and_refresh_token(current_token)
if new_token:
print("Token需要刷新")
else:
print("Token仍然有效")
ADMIN_TOKEN_EXPIRE_MINUTES,回退到 ACCESS_TOKEN_EXPIRE_MINUTES如需回滚到旧的token机制:
verify_token 函数总结:滑动过期Token机制大大提升了用户体验,用户在正常使用过程中永远不会遇到token超时问题,同时保持了系统的安全性。配置简单,使用方便,前端集成透明。