194 lines
5.5 KiB
Markdown
194 lines
5.5 KiB
Markdown
|
|
# 认证接口统一修复报告
|
|||
|
|
|
|||
|
|
## 问题分析
|
|||
|
|
|
|||
|
|
### 1. 认证方式不统一问题
|
|||
|
|
|
|||
|
|
系统中发现了三种不同的用户认证获取方式:
|
|||
|
|
|
|||
|
|
#### 方式一:`userService.getLoginUser(request)`
|
|||
|
|
- **使用范围**:大多数Controller
|
|||
|
|
- **文件示例**:
|
|||
|
|
- `UserController.java`
|
|||
|
|
- `MaterialController.java`
|
|||
|
|
- `ProductController.java`
|
|||
|
|
- `TopicController.java`
|
|||
|
|
- `ContentController.java`
|
|||
|
|
- 等等...
|
|||
|
|
|
|||
|
|
#### 方式二:`getCurrentUserId(request)`(自定义方法)
|
|||
|
|
- **使用范围**:`MaterialController.java`, `ContactController.java`, `MessageController.java`
|
|||
|
|
- **实现方式**:优先从request属性获取,然后调用userService.getLoginUser()
|
|||
|
|
|
|||
|
|
#### 方式三:`UserContextHolder.get()`
|
|||
|
|
- **使用范围**:Service实现类
|
|||
|
|
- **文件示例**:
|
|||
|
|
- `MaterialFolderServiceImpl.java`
|
|||
|
|
- `MaterialServiceImpl.java`
|
|||
|
|
- `ContentStyleServiceImpl.java`
|
|||
|
|
- `TargetAudienceServiceImpl.java`
|
|||
|
|
|
|||
|
|
### 2. 前端报告的具体问题
|
|||
|
|
|
|||
|
|
根据前端反馈:
|
|||
|
|
- `/materialfolder/tree` 接口返回 401 "用户未登录"
|
|||
|
|
- `/materialfolder/list` 接口返回 400 Bad Request
|
|||
|
|
- `/material/user/list` 接口工作正常
|
|||
|
|
|
|||
|
|
## 根本原因
|
|||
|
|
|
|||
|
|
1. **认证逻辑不一致**:不同接口使用不同的认证方式
|
|||
|
|
2. **上下文获取失败**:`UserContextHolder.get()` 在某些情况下返回null
|
|||
|
|
3. **AOP权限检查与手动检查冲突**:既有@AuthCheck注解又有手动权限验证
|
|||
|
|
|
|||
|
|
## 已修复内容
|
|||
|
|
|
|||
|
|
### 1. MaterialFolderController统一认证方式
|
|||
|
|
|
|||
|
|
**修复前**:
|
|||
|
|
```java
|
|||
|
|
// 使用UserContextHolder.get(),可能返回null
|
|||
|
|
User currentUser = UserContextHolder.get();
|
|||
|
|
if (currentUser == null) {
|
|||
|
|
return new BaseResponse<>(401, null, "用户未登录");
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**修复后**:
|
|||
|
|
```java
|
|||
|
|
// 统一使用getCurrentUserId方法
|
|||
|
|
Long userId = getCurrentUserId(request);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**修复的接口**:
|
|||
|
|
- `getFolderTree()` - 获取文件夹树
|
|||
|
|
- `getFolderById()` - 根据ID获取文件夹
|
|||
|
|
- `getUserFolders()` - 获取用户文件夹列表
|
|||
|
|
- `listFolderByPage()` - 分页获取文件夹列表
|
|||
|
|
|
|||
|
|
### 2. 添加权限检查
|
|||
|
|
|
|||
|
|
为 `listFolderByPage` 接口添加了:
|
|||
|
|
- `@AuthCheck(mustRole = Constant.DEFAULT_ROLE)` 注解
|
|||
|
|
- 用户ID设置:确保只返回当前用户的文件夹
|
|||
|
|
|
|||
|
|
### 3. 编译错误修复
|
|||
|
|
|
|||
|
|
修复了海报生成相关的编译错误:
|
|||
|
|
- `PosterGenerateServiceImpl.java`:修正了PosterContent字段使用
|
|||
|
|
- `PosterServiceImpl.java`:修正了TypeReference使用,改为ParameterizedTypeReference
|
|||
|
|
- `PosterGenerateResponse.java`:统一了字段命名
|
|||
|
|
|
|||
|
|
## 统一配置修复
|
|||
|
|
|
|||
|
|
### 1. 移除重复配置
|
|||
|
|
|
|||
|
|
**修复前**:
|
|||
|
|
```yaml
|
|||
|
|
# 两个不同的AIGC配置块
|
|||
|
|
external-services:
|
|||
|
|
poster-generate: ...
|
|||
|
|
aigc:
|
|||
|
|
server: ...
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**修复后**:
|
|||
|
|
```yaml
|
|||
|
|
# 统一到external-services配置
|
|||
|
|
external-services:
|
|||
|
|
poster-generate:
|
|||
|
|
base-url: http://8.138.116.153:2714
|
|||
|
|
# ...其他配置
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 推荐解决方案
|
|||
|
|
|
|||
|
|
### 1. 短期方案(已实施)
|
|||
|
|
|
|||
|
|
✅ 统一 MaterialFolderController 的认证方式
|
|||
|
|
✅ 修复编译错误
|
|||
|
|
✅ 统一配置文件
|
|||
|
|
|
|||
|
|
### 2. 长期方案(建议)
|
|||
|
|
|
|||
|
|
**2.1 认证方式标准化**
|
|||
|
|
建议统一使用 `userService.getLoginUser(request)` 方式:
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
// 推荐的标准写法
|
|||
|
|
@GetMapping("/example")
|
|||
|
|
@AuthCheck(mustRole = Constant.DEFAULT_ROLE)
|
|||
|
|
public BaseResponse<Object> example(HttpServletRequest request) {
|
|||
|
|
User currentUser = userService.getLoginUser(request);
|
|||
|
|
Long userId = currentUser.getId();
|
|||
|
|
// 业务逻辑...
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**2.2 Service层重构**
|
|||
|
|
Service实现类不应直接使用UserContextHolder,而应该从Controller层接收userId参数:
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
// Service接口
|
|||
|
|
public interface SomeService {
|
|||
|
|
List<SomeVO> getUserData(Long userId);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Controller调用
|
|||
|
|
@GetMapping("/data")
|
|||
|
|
@AuthCheck(mustRole = Constant.DEFAULT_ROLE)
|
|||
|
|
public BaseResponse<List<SomeVO>> getData(HttpServletRequest request) {
|
|||
|
|
User currentUser = userService.getLoginUser(request);
|
|||
|
|
List<SomeVO> result = someService.getUserData(currentUser.getId());
|
|||
|
|
return ResultUtils.success(result);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**2.3 移除冗余权限检查**
|
|||
|
|
在已有@AuthCheck注解的方法中,移除手动权限验证:
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
// 不推荐(冗余)
|
|||
|
|
@AuthCheck(mustRole = Constant.ADMIN_ROLE)
|
|||
|
|
public BaseResponse<Object> adminMethod(HttpServletRequest request) {
|
|||
|
|
User user = userService.getLoginUser(request);
|
|||
|
|
if (!Constant.ADMIN_ROLE.equals(user.getUserRole())) {
|
|||
|
|
throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "权限不足");
|
|||
|
|
}
|
|||
|
|
// ...
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 推荐(简洁)
|
|||
|
|
@AuthCheck(mustRole = Constant.ADMIN_ROLE)
|
|||
|
|
public BaseResponse<Object> adminMethod(HttpServletRequest request) {
|
|||
|
|
// 直接进行业务逻辑,@AuthCheck已处理权限验证
|
|||
|
|
// ...
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 测试验证
|
|||
|
|
|
|||
|
|
### 验证接口:
|
|||
|
|
1. ✅ `/materialfolder/tree` - 文件夹树接口
|
|||
|
|
2. ✅ `/materialfolder/list` - 文件夹列表接口
|
|||
|
|
3. ✅ `/materialfolder/folders` - 用户文件夹接口
|
|||
|
|
4. ✅ `/materialfolder/get/{id}` - 文件夹详情接口
|
|||
|
|
|
|||
|
|
### 预期结果:
|
|||
|
|
- 认证成功的用户能正常访问自己的数据
|
|||
|
|
- 返回正确的HTTP状态码和数据格式
|
|||
|
|
- 权限控制正常工作
|
|||
|
|
|
|||
|
|
## 风险评估
|
|||
|
|
|
|||
|
|
### 低风险:
|
|||
|
|
- ✅ MaterialFolderController修复(已测试编译通过)
|
|||
|
|
- ✅ 配置统一(向后兼容)
|
|||
|
|
|
|||
|
|
### 中等风险:
|
|||
|
|
- ⚠️ 其他Controller的认证方式统一(需要逐个测试)
|
|||
|
|
- ⚠️ Service层重构(影响范围较大)
|
|||
|
|
|
|||
|
|
## 总结
|
|||
|
|
|
|||
|
|
当前已修复了MaterialFolderController的认证问题和编译错误,这应该能解决前端报告的文件夹相关接口的401和400错误。建议在后续开发中逐步统一整个系统的认证方式,以避免类似问题再次出现。
|