7.4 KiB
7.4 KiB
前端Token API迁移指南
📋 概述
TokenController接口已经从POST请求体传递token的方式优化为GET请求头传递token的标准方式。如果前端需要使用这些接口,请参考以下迁移指南。
✅ 当前状态
经过检查,前端代码中没有直接使用以下接口:
/token/user-info/token/username/token/validate
前端主要使用的是AuthController中的接口:
/auth/user/info- 获取用户信息/auth/username- 获取用户名/auth/validateToken- 验证Token
因此,本次优化不需要修改前端代码。
📚 接口使用指南(如果将来需要)
1. 获取用户信息
旧方式(已废弃)
// ❌ 不推荐:POST请求,token在请求体中
const response = await http.post('/token/user-info', {
token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
})
新方式(推荐)
// ✅ 推荐:GET请求,token在请求头中(自动添加)
const response = await http.get('/token/user-info')
// 或者手动指定token(特殊场景)
const response = await http.get('/token/user-info', {
headers: {
'Authorization': `Bearer ${token}`
}
})
2. 获取用户名
旧方式(已废弃)
// ❌ 不推荐
const response = await http.post('/token/username', {
token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
})
新方式(推荐)
// ✅ 推荐
const response = await http.get('/token/username')
3. 验证Token
旧方式(已废弃)
// ❌ 不推荐
const response = await http.post('/token/validate', {
token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
})
新方式(推荐)
// ✅ 推荐
const response = await http.get('/token/validate')
🔧 HTTP请求工具配置
确保请求拦截器自动添加Token
大多数项目的HTTP工具已经配置了自动添加Authorization请求头的拦截器:
// utils/request.ts 或 utils/http.ts
import axios from 'axios'
const http = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL,
timeout: 10000
})
// 请求拦截器:自动添加Token
http.interceptors.request.use(
(config) => {
// 从localStorage获取token
const token = localStorage.getItem('access_token')
// 如果token存在,添加到请求头
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
},
(error) => {
return Promise.reject(error)
}
)
export { http }
如果项目还没有配置,请添加以下代码
// 1. 在请求拦截器中添加token
http.interceptors.request.use((config) => {
const token = localStorage.getItem('access_token')
if (token && !config.headers.Authorization) {
config.headers.Authorization = `Bearer ${token}`
}
return config
})
// 2. 在响应拦截器中处理401错误
http.interceptors.response.use(
(response) => response,
async (error) => {
if (error.response?.status === 401) {
// Token过期或无效,跳转到登录页
localStorage.removeItem('access_token')
window.location.href = '/login'
}
return Promise.reject(error)
}
)
📝 API服务封装示例
如果需要使用TokenController的接口,可以创建以下服务:
// services/token.ts
import { http } from '@/utils/request'
import type { UserInfo } from '@/types'
export const tokenApi = {
/**
* 获取用户信息
* Token会自动从请求头中获取
*/
getUserInfo(): Promise<UserInfo> {
return http.get('/token/user-info')
},
/**
* 获取用户名
* Token会自动从请求头中获取
*/
getUsername(): Promise<string> {
return http.get('/token/username')
},
/**
* 验证Token
* Token会自动从请求头中获取
*/
validateToken(): Promise<string> {
return http.get('/token/validate')
}
}
🎯 推荐使用AuthController接口
实际上,建议前端继续使用AuthController中的接口,因为它们提供了更完整的功能:
// services/auth.ts
import { http } from '@/utils/request'
export const authApi = {
/**
* 获取当前用户信息
* 推荐使用这个接口而不是 /token/user-info
*/
getUserInfo(): Promise<UserInfo> {
return http.get('/auth/user/info')
},
/**
* 获取用户名
* 推荐使用这个接口而不是 /token/username
*/
getUsername(): Promise<string> {
return http.get('/auth/username')
},
/**
* 验证Token
* 推荐使用这个接口而不是 /token/validate
*/
validateToken(): Promise<boolean> {
return http.get('/auth/validateToken')
}
}
🔍 接口对比
| 功能 | TokenController | AuthController | 推荐使用 |
|---|---|---|---|
| 获取用户信息 | GET /token/user-info |
GET /auth/user/info |
AuthController |
| 获取用户名 | GET /token/username |
GET /auth/username |
AuthController |
| 验证Token | GET /token/validate |
GET /auth/validateToken |
AuthController |
推荐理由:
- AuthController接口功能更完整
- 已经在项目中广泛使用
- 有更好的错误处理和日志记录
- 与认证流程集成更紧密
⚠️ 注意事项
1. Token存储位置
确保token存储在正确的位置:
// 登录成功后存储token
localStorage.setItem('access_token', response.accessToken)
// 登出时清除token
localStorage.removeItem('access_token')
2. Token格式
确保token以正确的格式发送:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
3. 错误处理
处理token相关的错误:
try {
const userInfo = await tokenApi.getUserInfo()
} catch (error) {
if (error.response?.status === 401) {
// Token无效或过期
console.error('Token无效,请重新登录')
// 跳转到登录页
router.push('/login')
}
}
4. Token刷新
实现token自动刷新机制:
http.interceptors.response.use(
(response) => response,
async (error) => {
const originalRequest = error.config
if (error.response?.status === 401 && !originalRequest._retry) {
originalRequest._retry = true
try {
// 尝试刷新token
const refreshToken = localStorage.getItem('refresh_token')
const response = await authApi.refreshToken({ refreshToken })
// 更新token
localStorage.setItem('access_token', response.accessToken)
// 重试原始请求
originalRequest.headers.Authorization = `Bearer ${response.accessToken}`
return http(originalRequest)
} catch (refreshError) {
// 刷新失败,跳转到登录页
localStorage.clear()
window.location.href = '/login'
return Promise.reject(refreshError)
}
}
return Promise.reject(error)
}
)
✅ 总结
- 当前状态:前端代码不需要修改,因为没有使用TokenController接口
- 推荐做法:继续使用AuthController接口
- 如果需要使用TokenController:
- 使用GET方法
- Token在请求头中自动传递
- 确保HTTP工具配置了请求拦截器
- 最佳实践:
- Token存储在localStorage
- 使用Bearer格式
- 实现自动刷新机制
- 处理401错误
这次优化使后端接口更加标准化和安全,为将来的扩展打下了良好的基础!