# 认证接口统一修复报告 ## 问题分析 ### 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 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 getUserData(Long userId); } // Controller调用 @GetMapping("/data") @AuthCheck(mustRole = Constant.DEFAULT_ROLE) public BaseResponse> getData(HttpServletRequest request) { User currentUser = userService.getLoginUser(request); List result = someService.getUserData(currentUser.getId()); return ResultUtils.success(result); } ``` **2.3 移除冗余权限检查** 在已有@AuthCheck注解的方法中,移除手动权限验证: ```java // 不推荐(冗余) @AuthCheck(mustRole = Constant.ADMIN_ROLE) public BaseResponse 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 adminMethod(HttpServletRequest request) { // 直接进行业务逻辑,@AuthCheck已处理权限验证 // ... } ``` ## 测试验证 ### 验证接口: 1. ✅ `/materialfolder/tree` - 文件夹树接口 2. ✅ `/materialfolder/list` - 文件夹列表接口 3. ✅ `/materialfolder/folders` - 用户文件夹接口 4. ✅ `/materialfolder/get/{id}` - 文件夹详情接口 ### 预期结果: - 认证成功的用户能正常访问自己的数据 - 返回正确的HTTP状态码和数据格式 - 权限控制正常工作 ## 风险评估 ### 低风险: - ✅ MaterialFolderController修复(已测试编译通过) - ✅ 配置统一(向后兼容) ### 中等风险: - ⚠️ 其他Controller的认证方式统一(需要逐个测试) - ⚠️ Service层重构(影响范围较大) ## 总结 当前已修复了MaterialFolderController的认证问题和编译错误,这应该能解决前端报告的文件夹相关接口的401和400错误。建议在后续开发中逐步统一整个系统的认证方式,以避免类似问题再次出现。