test-backend/.claude/security.md

126 lines
3.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 06 — 安全与日志规则
> **适用**:所有后端开发任务。
---
## 安全规则
### 认证检查(不变式)
每个需要登录的接口必须通过 Shiro 认证。JeecgBoot 默认全局拦截。
```java
// JeecgBoot 认证机制:
// 1. 所有 /sys/** /admin/** 默认需要登录
// 2. 白名单在 application.yml 配置
// 3. 权限注解:@RequiresPermissions / @RequiresRoles
// ✅ 接口加权限
@RequiresPermissions("user:add")
@PostMapping("/add")
public Result<?> add(...) { ... }
// ❌ 不要为了调试临时关认证
// ❌ 不要把需要认证的路径加到 shiro.excludeUrls
```
### 数据权限(租户隔离)
JeecgBoot 已通过 MyBatis-Plus 拦截器自动注入 tenant_id**但如果手写 SQL 必须手动加**。
```java
// ✅ 用 MyBatis-Plus 自动处理
taskService.list(new LambdaQueryWrapper<Task>().eq(Task::getStatus, "pending"));
// ❌ 手写 SQL 忘了加租户 → 租户A 看到租户B 的数据
@Select("SELECT * FROM task WHERE status = #{status}")
// ✅ 手写 SQL 正确写法
@Select("SELECT * FROM task WHERE status = #{status} AND tenant_id = #{tenantId}")
```
### 敏感信息保护
```java
// ✅ 密码字段不返回
@Entity
public class SysUser {
@JsonIgnore // ← 关键
private String password;
}
// ✅ 手机号脱敏返回VO 层处理)
userVO.setPhone(phone.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2"));
```
### 文件上传安全
```java
// ✅ 必须校验JeecgBoot 已内置部分,确认开启)
- 文件类型白名单只允许 jpg/png/pdf/doc/xlsx
- 文件大小上限单文件 10MB
- 文件名处理 UUID 重命名防路径穿越
- 存储路径不暴露原始文件名给前端
```
### 接口防刷
```java
// ✅ 敏感接口(登录/短信/支付)加限流
// JeecgBoot 使用 Sentinel 或自定义注解
@RateLimiter(count = 5, time = 60) // 60秒内最多5次
@PostMapping("/send-sms")
public Result<?> sendSms(...) { ... }
```
---
## 日志规则
### 日志级别
| 级别 | 场景 |
|------|------|
| ERROR | 数据库连不上、第三方接口失败、业务异常需要人工介入 |
| WARN | 降级处理、重试成功、配置缺失但有默认值 |
| INFO | 用户登录、任务创建、状态变更、定时任务执行 |
| DEBUG | 开发调试用,不入生产 |
### 日志内容
```java
// ✅ 关键操作
log.info("任务状态变更 taskId={} from={} to={} operator={}", taskId, oldStatus, newStatus, userId);
// ✅ 异常
log.error("调用第三方接口失败 url={}", url, e); // 最后一个参数是异常对象
// ❌ 不要这样
log.info("进来了");
log.info("user=" + user.toString()); // 可能打印密码
System.out.println("debug: " + xxx); // 永远不
```
### 禁止
| ❌ | 原因 |
|----|------|
| 循环里打 INFO | 日志爆炸 |
| 打印完整大对象 | 刷屏且可能泄露敏感数据 |
| 用 System.out.println | 不入日志文件 |
| 用 e.printStackTrace() | 不入日志框架 |
---
## 检查表
- [ ] 新接口需要认证(不在白名单中)
- [ ] 手写 SQL 加了租户隔离
- [ ] 敏感字段不返回给前端
- [ ] 文件上传有类型/大小校验
- [ ] 关键操作有 INFO 日志
- [ ] 异常有 ERROR 日志(带栈)
- [ ] 无硬编码密码/密钥