# 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().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 日志(带栈) - [ ] 无硬编码密码/密钥