代码优化
This commit is contained in:
@@ -0,0 +1,307 @@
|
||||
# 前端Token API迁移指南
|
||||
|
||||
## 📋 概述
|
||||
|
||||
TokenController接口已经从POST请求体传递token的方式优化为GET请求头传递token的标准方式。如果前端需要使用这些接口,请参考以下迁移指南。
|
||||
|
||||
## ✅ 当前状态
|
||||
|
||||
经过检查,前端代码中**没有直接使用**以下接口:
|
||||
- `/token/user-info`
|
||||
- `/token/username`
|
||||
- `/token/validate`
|
||||
|
||||
前端主要使用的是AuthController中的接口:
|
||||
- `/auth/user/info` - 获取用户信息
|
||||
- `/auth/username` - 获取用户名
|
||||
- `/auth/validateToken` - 验证Token
|
||||
|
||||
因此,**本次优化不需要修改前端代码**。
|
||||
|
||||
## 📚 接口使用指南(如果将来需要)
|
||||
|
||||
### 1. 获取用户信息
|
||||
|
||||
#### 旧方式(已废弃)
|
||||
```typescript
|
||||
// ❌ 不推荐:POST请求,token在请求体中
|
||||
const response = await http.post('/token/user-info', {
|
||||
token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
|
||||
})
|
||||
```
|
||||
|
||||
#### 新方式(推荐)
|
||||
```typescript
|
||||
// ✅ 推荐:GET请求,token在请求头中(自动添加)
|
||||
const response = await http.get('/token/user-info')
|
||||
|
||||
// 或者手动指定token(特殊场景)
|
||||
const response = await http.get('/token/user-info', {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### 2. 获取用户名
|
||||
|
||||
#### 旧方式(已废弃)
|
||||
```typescript
|
||||
// ❌ 不推荐
|
||||
const response = await http.post('/token/username', {
|
||||
token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
|
||||
})
|
||||
```
|
||||
|
||||
#### 新方式(推荐)
|
||||
```typescript
|
||||
// ✅ 推荐
|
||||
const response = await http.get('/token/username')
|
||||
```
|
||||
|
||||
### 3. 验证Token
|
||||
|
||||
#### 旧方式(已废弃)
|
||||
```typescript
|
||||
// ❌ 不推荐
|
||||
const response = await http.post('/token/validate', {
|
||||
token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
|
||||
})
|
||||
```
|
||||
|
||||
#### 新方式(推荐)
|
||||
```typescript
|
||||
// ✅ 推荐
|
||||
const response = await http.get('/token/validate')
|
||||
```
|
||||
|
||||
## 🔧 HTTP请求工具配置
|
||||
|
||||
### 确保请求拦截器自动添加Token
|
||||
|
||||
大多数项目的HTTP工具已经配置了自动添加Authorization请求头的拦截器:
|
||||
|
||||
```typescript
|
||||
// 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 }
|
||||
```
|
||||
|
||||
### 如果项目还没有配置,请添加以下代码
|
||||
|
||||
```typescript
|
||||
// 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的接口,可以创建以下服务:
|
||||
|
||||
```typescript
|
||||
// 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中的接口,因为它们提供了更完整的功能:
|
||||
|
||||
```typescript
|
||||
// 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存储在正确的位置:
|
||||
```typescript
|
||||
// 登录成功后存储token
|
||||
localStorage.setItem('access_token', response.accessToken)
|
||||
|
||||
// 登出时清除token
|
||||
localStorage.removeItem('access_token')
|
||||
```
|
||||
|
||||
### 2. Token格式
|
||||
确保token以正确的格式发送:
|
||||
```
|
||||
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
```
|
||||
|
||||
### 3. 错误处理
|
||||
处理token相关的错误:
|
||||
```typescript
|
||||
try {
|
||||
const userInfo = await tokenApi.getUserInfo()
|
||||
} catch (error) {
|
||||
if (error.response?.status === 401) {
|
||||
// Token无效或过期
|
||||
console.error('Token无效,请重新登录')
|
||||
// 跳转到登录页
|
||||
router.push('/login')
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Token刷新
|
||||
实现token自动刷新机制:
|
||||
```typescript
|
||||
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)
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
## ✅ 总结
|
||||
|
||||
1. **当前状态**:前端代码不需要修改,因为没有使用TokenController接口
|
||||
2. **推荐做法**:继续使用AuthController接口
|
||||
3. **如果需要使用TokenController**:
|
||||
- 使用GET方法
|
||||
- Token在请求头中自动传递
|
||||
- 确保HTTP工具配置了请求拦截器
|
||||
4. **最佳实践**:
|
||||
- Token存储在localStorage
|
||||
- 使用Bearer格式
|
||||
- 实现自动刷新机制
|
||||
- 处理401错误
|
||||
|
||||
这次优化使后端接口更加标准化和安全,为将来的扩展打下了良好的基础!
|
||||
Reference in New Issue
Block a user