Files
global-coding-governance/java-coding-style/references/04-异常日志与安全.md
2026-07-25 23:45:09 +08:00

4.0 KiB
Raw Permalink Blame History

异常、日志与安全

异常

  • 必须:异常表达失败语义,不用异常控制正常分支。
  • 必须:不要直接抛出宽泛的 ExceptionRuntimeExceptionThrowable;使用标准的精确异常或稳定的领域异常。
  • 必须:不得空 catch、只打印堆栈或吞掉异常。转换异常时保留 cause,并补充不含敏感数据的上下文。
  • 必须:同一层通常选择“处理并记录”或“向上抛出”,避免每层重复记录同一异常。
  • 必须:可通过前置检查避免的错误应先校验;并发竞态场景仍以原子操作结果为准。
  • 必须:资源使用 try-with-resourcesfinally 不得用 return 覆盖原返回值或异常。
  • 必须:捕获范围保持最小,不用一个大 try 模糊具体失败点。
  • 推荐:对外错误模型稳定、可追踪且不泄漏内部栈、SQL、文件路径或依赖细节。

日志

  • 必须:使用项目日志门面,不使用 System.outSystem.errprintStackTrace
  • 必须:参数化记录日志,不做无必要的字符串拼接;异常对象作为日志框架支持的异常参数传入。
  • 必须:日志级别符合可操作性:预期业务拒绝通常不是 error,系统不可恢复失败不能只写 debug。
  • 必须:禁止记录密码、令牌、密钥、完整证件号、银行卡、Cookie、会话或未脱敏请求体。
  • 推荐:记录稳定的事件、结果、耗时、非敏感标识和 trace/correlation id;避免在高频循环中刷屏。
  • 必须:日志不得改变业务行为;日志表达式不得触发远程调用、延迟加载或明显昂贵计算。
  • 推荐:项目同时使用 SLF4J 和 Lombok 时采用 @Slf4j,否则遵循项目统一的日志门面与声明方式。
  • 必须error 仅用于由当前层最终处理、需要人工介入的系统失败,并包含异常堆栈和已脱敏的定位上下文。
  • 推荐warn 用于异常但可恢复、仍需要关注的状态。
  • 推荐:预期业务拒绝通常使用 info 或不记录,避免制造告警噪声。
  • 必须:同一异常只在负责最终处理的层记录一次;转换异常时保留原始 cause,不在中间层重复打印堆栈。

输入与权限

  • 必须:所有外部输入在信任边界验证类型、长度、范围、格式、集合规模和允许值;前端校验不能替代服务端校验。
  • 必须:认证后仍要做功能级和对象级授权,不能只检查“是否登录”。
  • 必须:SQL 使用参数绑定;排序字段、表名、列名等不可绑定的元数据必须采用服务端白名单。
  • 必须:输出到 HTML、脚本、URL、日志或命令时按目标上下文编码;不要自行拼接转义规则。
  • 必须:状态变更接口按框架能力启用 CSRF、防重放、幂等或频控措施。
  • 必须:文件路径规范化并限制在允许根目录;URL 请求限制协议、主机、重定向和内网地址以防 SSRF。
  • 必须:禁止反序列化不可信 Java 原生对象流;JSON 多态、表达式、脚本和正则能力采用最小白名单。
  • 必须:凭据来自受控配置或密钥服务,不写入源码、测试、日志和错误响应。
  • 推荐:使用成熟安全库和框架默认防护,不自行实现密码学、会话、签名或随机令牌算法。

事务与一致性

  • 必须:事务边界与业务原子性一致,避免在长事务中执行远程调用或不可控 I/O。
  • 必须:明确异常类型是否触发回滚;框架代理、自调用和异步边界可能使事务注解失效。
  • 必须:事务方法捕获异常后必须重新抛出、显式标记回滚或完成可靠补偿。
  • 必须:重试仅用于可重试失败,并要求操作幂等、退避、次数上限和可观测性。
  • 推荐:跨系统一致性采用项目既有 outbox、事件或补偿机制,不临时发明“先写库再发消息”的脆弱流程。