Files
happy-life-star/TOKEN_CONTROLLER_OPTIMIZATION.md
T
2025-10-13 10:43:08 +08:00

7.9 KiB
Raw Blame History

TokenController优化总结

🎯 优化目标

将TokenController从使用请求体传递token的方式改为标准的从请求头自动获取token的方式,符合RESTful API最佳实践。

完成的优化

1. 修改TokenController接口

优化前

@PostMapping("/user-info")
public Result<UserInfoResponse> getUserInfoByToken(@RequestBody @Validated TokenRequest request) {
    UserInfoResponse userInfo = tokenService.getUserInfoByToken(request.getToken());
    return Result.success(userInfo);
}

问题

  • 使用POST方法获取数据(不符合RESTful规范)
  • Token在请求体中传递(不安全,不标准)
  • 需要额外的TokenRequest类封装
  • 客户端需要构造请求体

优化后

@GetMapping("/user-info")
@Operation(summary = "获取用户信息", description = "通过请求头中的token获取当前用户信息")
public Result<UserInfoResponse> getUserInfoByToken(HttpServletRequest request) {
    UserInfoResponse userInfo = tokenService.getUserInfoByToken(request);
    return Result.success(userInfo);
}

改进

  • 使用GET方法获取数据(符合RESTful规范)
  • Token从请求头Authorization自动提取
  • 不需要额外的Request类
  • 客户端只需设置请求头

2. 删除TokenRequest类

删除的文件

  • backend-single/src/main/java/com/emotion/dto/request/TokenRequest.java

原因

  • 不再需要通过请求体传递token
  • 简化代码结构
  • 减少不必要的类

3. 添加API文档注解

@Tag(name = "Token管理", description = "Token验证和用户信息获取")
public class TokenController {
    
    @GetMapping("/user-info")
    @Operation(summary = "获取用户信息", description = "通过请求头中的token获取当前用户信息")
    public Result<UserInfoResponse> getUserInfoByToken(HttpServletRequest request) {
        // ...
    }
}

📊 接口变更对比

接口1: 获取用户信息

优化前

  • 请求方式: POST /token/user-info
  • 请求头: 无
  • 请求体:
    {
      "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
    }
    

优化后

  • 请求方式: GET /token/user-info
  • 请求头:
    Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
    
  • 请求体: 无

接口2: 获取用户名

优化前

  • 请求方式: POST /token/username
  • 请求头: 无
  • 请求体:
    {
      "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
    }
    

优化后

  • 请求方式: GET /token/username
  • 请求头:
    Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
    
  • 请求体: 无

接口3: 验证Token

优化前

  • 请求方式: POST /token/validate
  • 请求头: 无
  • 请求体:
    {
      "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
    }
    

优化后

  • 请求方式: GET /token/validate
  • 请求头:
    Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
    
  • 请求体: 无

🔧 Token提取机制

TokenUtil已经实现了标准的token提取逻辑:

public String extractToken(HttpServletRequest request) {
    // 1. 优先从Authorization请求头获取(标准方式)
    String authHeader = request.getHeader("Authorization");
    if (authHeader != null && authHeader.startsWith("Bearer ")) {
        return authHeader.substring(7);
    }

    // 2. 备用方案:从请求参数获取
    String tokenParam = request.getParameter("token");
    if (tokenParam != null && !tokenParam.trim().isEmpty()) {
        return tokenParam.trim();
    }

    return null;
}

支持的Token传递方式

  1. 标准方式(推荐):Authorization: Bearer {token}
  2. 备用方式URL参数 ?token={token}

🚀 前端调用示例

优化前(不推荐)

// 需要在请求体中传递token
const response = await http.post('/token/user-info', {
  token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
})

优化后(推荐)

// Token自动从localStorage获取并添加到请求头
const response = await http.get('/token/user-info')

// 或者手动设置(如果需要)
const response = await http.get('/token/user-info', {
  headers: {
    'Authorization': `Bearer ${token}`
  }
})

📝 优化收益

1. 符合标准规范

  • 遵循RESTful API设计原则
  • 使用标准的Authorization请求头
  • GET方法用于查询,POST方法用于修改

2. 提升安全性

  • Token不在请求体中暴露
  • 减少token在日志中被记录的风险
  • 符合OAuth 2.0和JWT标准

3. 简化代码

  • 删除不必要的TokenRequest类
  • 减少代码维护成本
  • 统一token处理方式

4. 改善开发体验

  • 前端不需要构造请求体
  • 自动从请求头提取token
  • 更清晰的API文档

5. 提高可维护性

  • 代码结构更清晰
  • 职责分离更明确
  • 便于后续扩展

🔍 相关文件变更

修改的文件

  1. backend-single/src/main/java/com/emotion/controller/TokenController.java
    • 修改所有接口从POST改为GET
    • 参数从@RequestBody TokenRequest改为HttpServletRequest
    • 添加Swagger API文档注解
    • 添加详细的注释说明

删除的文件

  1. backend-single/src/main/java/com/emotion/dto/request/TokenRequest.java
    • 不再需要此类

未修改的文件

  1. TokenService.java - 接口已经是标准方式
  2. TokenServiceImpl.java - 实现已经是标准方式
  3. TokenUtil.java - 工具类已经支持标准方式

测试验证

测试用例

1. 测试获取用户信息

curl -X GET http://localhost:8080/token/user-info \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

预期结果

{
  "code": 200,
  "message": "操作成功",
  "data": {
    "userId": "user_123",
    "username": "testuser",
    "email": "test@example.com"
  }
}

2. 测试获取用户名

curl -X GET http://localhost:8080/token/username \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

预期结果

{
  "code": 200,
  "message": "操作成功",
  "data": "testuser"
}

3. 测试验证Token

curl -X GET http://localhost:8080/token/validate \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

预期结果

{
  "code": 200,
  "message": "操作成功",
  "data": "user_123"
}

4. 测试无效Token

curl -X GET http://localhost:8080/token/user-info \
  -H "Authorization: Bearer invalid_token"

预期结果

{
  "code": 401,
  "message": "访问令牌无效或已过期",
  "data": null
}

5. 测试缺少Token

curl -X GET http://localhost:8080/token/user-info

预期结果

{
  "code": 401,
  "message": "未提供访问令牌",
  "data": null
}

📚 最佳实践

1. Token传递方式

  • 推荐:使用Authorization: Bearer {token}请求头
  • ⚠️ 备用:使用URL参数?token={token}(仅在特殊场景)
  • 不推荐:在请求体中传递token

2. HTTP方法选择

  • GET:获取资源(如获取用户信息、验证token)
  • POST:创建资源(如登录、注册)
  • PUT/PATCH:更新资源
  • DELETE:删除资源

3. 安全建议

  • 使用HTTPS传输token
  • 设置合理的token过期时间
  • 实现token刷新机制
  • 记录token使用日志

🎯 总结

通过这次优化,TokenController已经完全符合RESTful API标准和安全最佳实践:

  1. 标准化:使用标准的Authorization请求头传递token
  2. 简化:删除不必要的TokenRequest类
  3. 规范化GET方法用于查询操作
  4. 文档化:添加完整的Swagger API文档
  5. 安全性Token不在请求体中暴露

现在TokenController的实现更加专业、安全、易用!