feat: 实现JWT失效机制和优化订单精度

- 实现JWT tokenVersion机制,修改密码后所有token自动失效
  - 在User实体中添加tokenVersion字段
  - 创建V2数据库迁移文件添加token_version列
  - 修改密码时递增tokenVersion
  - JWT中包含tokenVersion,验证时检查版本是否匹配
  - 支持HTTP API和WebSocket连接的token验证

- 优化订单精度计算,与SDK保持一致
  - BUY订单:使用原始价格计算makerAmount,避免精度丢失
  - SELL订单:使用原始价格计算takerAmount,确保与SDK结果一致
  - 修复之前使用舍入后价格导致的精度问题

- 前端自动登出功能
  - 响应拦截器检测认证错误(code 2001-2999)自动登出
  - 支持成功响应和错误响应中的认证错误检测
  - 自动清除token、断开WebSocket并跳转登录页
This commit is contained in:
WrBug
2025-12-03 23:01:43 +08:00
parent 2ad558da36
commit 166bec737b
9 changed files with 157 additions and 34 deletions
+27 -9
View File
@@ -43,6 +43,23 @@ apiClient.interceptors.request.use(
}
)
/**
* 处理认证错误(自动登出)
*/
const handleAuthError = (code: number) => {
// 检查是否是认证错误(2001-2999)
if (code >= 2001 && code < 3000) {
// 清除 token
removeToken()
// 断开 WebSocket 连接
wsManager.disconnect()
// 跳转到登录页(避免循环跳转)
if (window.location.pathname !== '/login' && window.location.pathname !== '/reset-password') {
window.location.href = '/login'
}
}
}
/**
* 响应拦截器
*/
@@ -53,6 +70,14 @@ apiClient.interceptors.response.use(
if (newToken) {
setToken(newToken)
}
// 检查响应体中的 code,如果是认证错误,自动登出
// 后端可能返回 200 状态码,但 code 是 2001(认证失败)
const data = response.data as ApiResponse<any>
if (data && data.code !== undefined) {
handleAuthError(data.code)
}
return response
},
(error: AxiosError<ApiResponse<any>>) => {
@@ -61,15 +86,8 @@ apiClient.interceptors.response.use(
const data = response.data
// 检查是否是认证错误(2001-2999)
if (data && data.code >= 2001 && data.code < 3000) {
// 清除 token
removeToken()
// 断开 WebSocket 连接
wsManager.disconnect()
// 跳转到登录页(避免循环跳转)
if (window.location.pathname !== '/login' && window.location.pathname !== '/reset-password') {
window.location.href = '/login'
}
if (data && data.code !== undefined) {
handleAuthError(data.code)
}
console.error('API 错误:', data)