防止敏感堆栈信息外泄的关键是分层控制:用户端模糊提示、开发端保留完整上下文、日志端脱敏过滤;所有异常须经@ControllerAdvice拦截并返回标准化错误体,禁用直接输出getMessage()或printStackTrace()。

防止敏感堆栈信息外泄,关键不是“不记录”,而是“分层控制”:对用户模糊提示、对开发保留完整上下文、对日志脱敏过滤。
统一拦截并替换前端响应
禁用直接返回异常 getMessage() 或 printStackTrace()。所有控制器异常必须经 @ControllerAdvice 拦截,返回标准化错误体。
- 用通用提示替代原始消息,如 “操作失败,请稍后重试” 而非 “Connection refused: db-prod:5432”
- 响应中可携带唯一 requestId,便于后台日志关联,但不暴露任何路径、主机名、SQL 片段或类名
- 开发环境可开启详细错误(仅限 localhost),生产环境强制关闭
日志记录要带脱敏和分级
SLF4J 或 Log4j 记录时,必须用 logger.error("业务动作失败", e) 格式,而非 e.printStackTrace();同时前置清洗敏感内容。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 手机号、身份证、邮箱、token 等字段在拼入日志前必须掩码,例如 138****1234、u***@x.com
- 禁用 DEBUG/TRACE 级别上线,ERROR 日志禁止写入公开可查的文件或监控面板
- 数据库异常优先记录 e.getSQLState() 和 e.getErrorCode(),它们是标准码,不含表名、驱动版本等泄露项
封装底层异常,抑制冗余堆栈
第三方库抛出的异常(如 SQLException、HttpClientException)不能原样向上抛,需包装为自定义 AppException,并控制堆栈可见性。
立即学习“Java免费学习笔记(深入)”;
- 构造时传入 cause,确保根因可追溯;但子类应调用 e.addSuppressed() 或显式 suppressStackTrace() 避免打印多层 Caused by
- 避免 new BusinessException("DB timeout", e) 这种写法——它会把整个 JDBC 堆栈打出来,干扰排查重点
- 敏感操作(如登录、支付)抛出的异常应语义模糊,例如 AuthenticationException("验证未通过"),不提账号、密码、锁定状态
禁用危险输出方式
很多泄露源于开发习惯性调试残留,上线前必须清理。
- 删除所有 System.out.println、e.printStackTrace()、logger.info("debug: " + obj) 类语句
- 禁用全局异常处理器中的 toString() 输出,尤其不要拼接 e.getClass().getName() + ":" + e.getMessage()
- 模板引擎(如 Thymeleaf、Freemarker)错误页面不得启用 development mode,避免展示源码路径和变量值

















