网关层异常脱敏核心是“拦截—过滤—重写—返回”,统一拦截非2xx响应,清洗敏感信息后返回前端模糊安全提示,后端日志保留脱敏后的完整上下文并支持多租户差异化提示。

网关层做异常脱敏,核心是“拦截—过滤—重写—返回”,不把原始异常堆栈或敏感细节透出,而是统一转成前端友好的业务提示。前端只看到模糊、安全、可读的错误信息,后端日志里才保留完整上下文供排查。
统一拦截所有下游异常
在网关(如 Spring Cloud Gateway 或自研网关)中,用全局异常处理器或 Filter 拦截后端服务返回的响应体和状态码。重点不是捕获 Java 异常对象,而是识别 HTTP 响应中的错误信号:比如 5xx 状态码、含 error 字段的 JSON、或特定错误头(如 X-Error-Type: DB_TIMEOUT)。
- 对非 2xx 响应,解析原始 body(如 Jackson 解析为 JsonNode),提取原始错误信息
- 若后端已返回结构化错误(如 { "code": "DB_CONN_FAIL", "message": "Connection refused: db-prod:3306" }),直接丢弃 message 字段,仅保留 code 用于日志追踪
- 若后端返回的是裸异常堆栈(如 Tomcat 默认 HTML 错误页或纯文本 stacktrace),需先清洗再重写
过滤并重写错误提示内容
重写原则是:去掉技术细节、路径、类名、SQL 片段、账号字段名、IP 地址等。只保留用户能理解的业务语义,且不暗示系统弱点。
PigX UI Pro 前端开发指南 - Vue 3 + TypeScript + Element Plus。当用户提到 PigX UI、PigX 前端、lgb-mgui 项目、Vue 3 企业级后台开发、Element Plus 后台开发时使用此技能。
- 禁止出现:“Caused by: java.sql.SQLTimeoutException”、“at com.xxx.dao.UserDao.findById(UserDao.java:42)”、“/opt/app/config/jdbc.properties”
- 允许输出:“请求处理失败,请稍后重试”、“当前服务暂时不可用”、“操作未成功,请检查网络后重试”
- 错误码(如 E5001)仅用于内部日志关联,前端不解析含义,也不展示给用户
日志中保留脱敏后的完整上下文
用户看不到的错误详情,必须确保可定位根因。关键不是“记不记”,而是“怎么记”。
立即学习“Java免费学习笔记(深入)”;
- 记录时传入 Throwable 对象:logger.error("Failed to fetch user profile for id {}", userId, e)
- 对异常消息中的敏感值做预脱敏:手机号、身份证、token、邮箱等字段,在写入日志前调用 maskPhone()、maskIdCard() 等工具方法清理
- 避免在日志中拼接原始异常 toString(),更不能把 e.printStackTrace() 写进 log 文件
- 异步线程或 Netty 事件循环中抛出的异常容易丢失,需设置 Thread.setDefaultUncaughtExceptionHandler 补漏
支持多租户/多渠道差异化提示
同一错误在不同调用方场景下,提示语气或粒度可不同。网关可通过请求头识别上下文,动态选择提示模板。
- 例如 X-App-ID: admin-console → 提示“系统管理后台暂不可用,请联系运维”
- X-App-ID: mobile-app → 提示“网络繁忙,请稍后重试”
- X-Env: test → 可额外附加 traceId 和简要错误类型(仅供测试人员查看)
- 策略配置支持表达式,如 messageTemplate = "E${code}#mobile" → 匹配到后自动套用移动端友好文案

















