feat :init

This commit is contained in:
2025-11-02 19:34:16 +08:00
commit b767041311
617 changed files with 124099 additions and 0 deletions

143
故障分析报告.md Normal file
View File

@@ -0,0 +1,143 @@
# Xiaozhi ESP32 Server - 用户未登录导致数据库插入失败故障分析
## 故障现象
- **错误信息**: `java.sql.SQLIntegrityConstraintViolationException: Column 'userId' cannot be null`
- **发生时间**: 2025-07-08 09:44:58 - 09:50:33
- **影响接口**: `/api/config/add`
- **错误频率**: 多次重复出现
## 问题分析
### 1. 根本原因
用户在未登录状态下访问了需要认证的接口 `/api/config/add`,导致:
- `CmsUtils.getUserId()` 返回 null
- 数据库插入时 userId 字段为 null
- 违反数据库 NOT NULL 约束
### 2. 认证机制分析
#### 当前认证流程:
1. `AuthenticationInterceptor` 拦截所有请求
2. 检查会话中是否有用户信息
3. 如果没有,尝试从 Cookie 中获取用户名并自动登录
4. 如果都失败,返回 401 未授权错误
#### 配置问题:
```java
// WebMvcConfig.java
registry.addInterceptor(authenticationInterceptor)
.addPathPatterns("/**")
.excludePathPatterns(
"/api/user/login",
"/api/user/register",
"/api/device/ota",
"/audio/**",
"/uploads/**",
"/avatar/**",
"/ws/**"
);
```
`/api/config/**` 路径需要认证,但拦截器似乎没有正确拦截。
### 3. 可能的原因
1. **Cookie 认证失败**
- Cookie 中的用户名存在,但数据库中找不到对应用户
- Cookie 认证成功,但没有正确设置 userId
2. **请求处理顺序问题**
- 拦截器执行顺序可能有问题
- `RequestContextHolder` 的属性设置时机不对
3. **前端问题**
- 前端可能在用户未登录时错误地调用了接口
- 前端可能缓存了过期的认证信息
## 解决方案
### 1. 短期修复(已实施)
`ConfigController` 中添加显式的登录检查:
```java
@PostMapping("/add")
@ResponseBody
public AjaxResult add(SysConfig config) {
try {
// 获取当前用户ID
Integer userId = CmsUtils.getUserId();
// 检查用户是否已登录
if (userId == null) {
return AjaxResult.error(HttpStatus.FORBIDDEN, "用户未登录,请先登录");
}
config.setUserId(userId);
configService.add(config);
return AjaxResult.success();
} catch (Exception e) {
logger.error(e.getMessage(), e);
return AjaxResult.error();
}
}
```
### 2. 长期改进建议
#### 2.1 修复认证拦截器
确保拦截器在用户未登录时正确返回 401 错误,而不是让请求继续执行。
#### 2.2 统一认证检查
创建一个基础控制器方法,统一处理用户认证检查:
```java
protected Integer requireUserId() {
Integer userId = CmsUtils.getUserId();
if (userId == null) {
throw new UnauthorizedException("用户未登录");
}
return userId;
}
```
#### 2.3 全局异常处理
`GlobalExceptionHandler` 中添加对 `UnauthorizedException` 的处理。
#### 2.4 前端改进
- 在 API 调用前检查用户登录状态
- 收到 401 错误时自动跳转到登录页面
- 清理过期的认证信息
### 3. 需要检查的其他接口
以下接口也使用了 `CmsUtils.getUserId()`,需要添加类似的检查:
- `/api/role/add`
- `/api/role/update`
- `/api/role/query`
- `/api/device/add`
- `/api/device/update`
- `/api/device/query`
- `/api/agent/add`
- `/api/template/add`
- `/api/template/update`
- `/api/template/query`
## 监控建议
1. **添加日志监控**
- 记录所有认证失败的请求
- 监控 userId 为 null 的情况
2. **添加告警**
- 当出现大量认证失败时发送告警
- 监控数据库约束违反错误
3. **定期审查**
- 审查所有需要用户认证的接口
- 确保认证机制正常工作
## 总结
这是一个典型的认证机制失效导致的数据完整性问题。虽然已经通过在控制器层添加检查来临时解决,但根本问题是认证拦截器没有正确工作。建议尽快修复拦截器,并在所有需要用户认证的接口中添加统一的认证检查机制。