187 lines
5.9 KiB
Markdown
187 lines
5.9 KiB
Markdown
# 游客模式401问题彻底修复方案
|
||
|
||
**问题**: 后端返回401错误,导致游客模式下无法看到课程数据
|
||
|
||
---
|
||
|
||
## 🔍 问题诊断
|
||
|
||
### 当前状态
|
||
1. ✅ 前端已配置游客白名单
|
||
2. ✅ 前端已添加 error.silent 检查
|
||
3. ✅ 后端WebMvcConfig已排除这些接口
|
||
4. ✅ JWT拦截器配置为无token时放行
|
||
5. ❌ **但后端仍然返回401错误**
|
||
|
||
### 控制台日志分析
|
||
```
|
||
[Request] 游客模式,白名单接口业务码401,静默失败,不影响页面显示: /api/special-course/list
|
||
{code: 401, message: "未登录", data: {…}, silent: true}
|
||
```
|
||
|
||
**结论**: 后端确实返回了401错误,说明有其他地方在检查用户登录状态
|
||
|
||
---
|
||
|
||
## 🎯 可能的原因
|
||
|
||
### 原因1: Service层检查了用户登录
|
||
某些Service方法可能使用了 `@CurrentUser` 注解或手动检查userId
|
||
|
||
### 原因2: 数据库中没有数据
|
||
即使接口正常,如果数据库中没有课程数据,也会显示空列表
|
||
|
||
### 原因3: Controller中有隐式的登录检查
|
||
虽然没有显式的权限注解,但可能在方法内部检查了userId
|
||
|
||
---
|
||
|
||
## ✅ 解决方案
|
||
|
||
### 方案1: 检查并修复Service层(推荐)
|
||
|
||
#### 步骤1: 检查Service实现
|
||
查看这三个Service的实现,确保没有强制要求userId:
|
||
- `SpecialCourseService`
|
||
- `InterestCourseService`
|
||
- `AssessmentServiceService`
|
||
|
||
#### 步骤2: 修改Service方法
|
||
如果Service方法需要userId,改为可选参数:
|
||
```java
|
||
// 修改前
|
||
public List<Course> getCourseList(Long userId) {
|
||
if (userId == null) {
|
||
throw new BusinessException(401, "未登录");
|
||
}
|
||
// ...
|
||
}
|
||
|
||
// 修改后
|
||
public List<Course> getCourseList(Long userId) {
|
||
// userId可以为null,游客模式下不影响查询
|
||
// ...
|
||
}
|
||
```
|
||
|
||
### 方案2: 创建测试数据
|
||
|
||
如果数据库中没有数据,创建一些测试数据:
|
||
|
||
```sql
|
||
-- 插入专项突破课程测试数据
|
||
INSERT INTO special_course (name, category, sub_category, description, price, duration, icon, status, sort_order, created_at, updated_at)
|
||
VALUES
|
||
('数学思维训练', 'math', '逻辑思维', '培养数学逻辑思维能力', 299.00, 60, '🧮', 1, 1, NOW(), NOW()),
|
||
('英语口语突破', 'english', '口语表达', '提升英语口语表达能力', 399.00, 90, '🗣️', 1, 2, NOW(), NOW()),
|
||
('阅读理解提升', 'language', '阅读理解', '提高阅读理解和分析能力', 199.00, 45, '📖', 1, 3, NOW(), NOW());
|
||
|
||
-- 插入兴趣培养课程测试数据
|
||
INSERT INTO interest_course (name, category, description, price, duration, icon, student_count, rating, status, created_at, updated_at)
|
||
VALUES
|
||
('钢琴入门', '音乐', '从零开始学习钢琴演奏', 599.00, 120, '🎹', 156, 4.8, 1, NOW(), NOW()),
|
||
('绘画启蒙', '美术', '培养绘画兴趣和基础技能', 399.00, 90, '🎨', 203, 4.7, 1, NOW(), NOW()),
|
||
('编程思维', '科技', '培养计算思维和编程能力', 699.00, 150, '💻', 89, 4.9, 1, NOW(), NOW());
|
||
|
||
-- 插入测评服务测试数据
|
||
INSERT INTO assessment_service (name, category, description, price, duration, icon, assessor_name, assessor_title, rating, appointment_count, status, created_at, updated_at)
|
||
VALUES
|
||
('学业能力测评', '学业', '全面评估学生学业水平', 299.00, 90, '📊', '张老师', '资深教育专家', 4.9, 234, 1, NOW(), NOW()),
|
||
('心理健康测评', '心理', '了解学生心理状态', 199.00, 60, '🧠', '李老师', '心理咨询师', 4.8, 178, 1, NOW(), NOW()),
|
||
('兴趣特长测评', '兴趣', '发现学生兴趣和特长', 249.00, 75, '🎯', '王老师', '职业规划师', 4.7, 145, 1, NOW(), NOW());
|
||
```
|
||
|
||
### 方案3: 后端直接返回空数据而不是401
|
||
|
||
修改Controller,即使没有userId也返回空列表:
|
||
|
||
```java
|
||
@GetMapping("/list")
|
||
public Result<List<Course>> getCourseList(@CurrentUser(required = false) Long userId, ...) {
|
||
// userId可以为null,游客模式下返回公开课程
|
||
List<Course> courses = courseService.getCourseList(userId);
|
||
return Result.success(courses);
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 🔧 立即执行的修复步骤
|
||
|
||
### 步骤1: 检查数据库
|
||
运行脚本检查是否有数据:
|
||
```
|
||
Archive/[一次性]执行检查课程数据-2026-02-01.bat
|
||
```
|
||
|
||
### 步骤2: 如果没有数据,插入测试数据
|
||
创建并执行SQL脚本插入测试数据
|
||
|
||
### 步骤3: 重启后端服务
|
||
```
|
||
cd peidu/backend
|
||
mvn clean package -DskipTests
|
||
java -jar target/peidu-backend.jar
|
||
```
|
||
|
||
### 步骤4: 测试后端接口
|
||
```
|
||
Archive/[一次性]测试后端匿名访问-游客模式-2026-02-01.bat
|
||
```
|
||
|
||
### 步骤5: 如果还是401,检查Service层
|
||
查看Service实现,移除强制的userId检查
|
||
|
||
---
|
||
|
||
## 📝 预期结果
|
||
|
||
修复后:
|
||
- ✅ 游客访问课程列表 → 返回200和数据
|
||
- ✅ 前端正常显示课程列表
|
||
- ✅ 不再显示401错误
|
||
- ✅ 游客可以浏览所有公开课程
|
||
|
||
---
|
||
|
||
## 🚨 注意事项
|
||
|
||
1. **不要在公开接口中检查userId**
|
||
- 游客模式下userId为null是正常的
|
||
- 只在需要用户信息的接口中检查userId
|
||
|
||
2. **区分公开接口和私有接口**
|
||
- 公开接口:课程列表、详情、搜索等
|
||
- 私有接口:购买、收藏、我的课程等
|
||
|
||
3. **数据权限控制**
|
||
- 游客可以看到所有公开课程
|
||
- 但不能购买、不能看到价格敏感信息
|
||
|
||
---
|
||
|
||
## 💡 最佳实践
|
||
|
||
```java
|
||
@GetMapping("/list")
|
||
public Result<List<Course>> getCourseList(
|
||
@CurrentUser(required = false) Long userId, // ✅ required = false
|
||
@RequestParam(required = false) String category
|
||
) {
|
||
// 游客模式:userId = null,返回公开课程
|
||
// 登录模式:userId != null,可以返回个性化推荐
|
||
List<Course> courses = courseService.getCourseList(userId, category);
|
||
return Result.success(courses);
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 🎯 下一步
|
||
|
||
1. 先运行检查数据脚本,确认是否有数据
|
||
2. 如果没有数据,插入测试数据
|
||
3. 如果有数据但还是401,检查Service层实现
|
||
4. 修改Service层,移除强制的userId检查
|
||
5. 重启后端,测试接口
|