如何配置我的 Spring Boot 服务,以便 500 之类的错误不会泄露诸如堆栈跟踪之类的实现细节。
{
"timestamp": "2019/05/01 15:06:17",
"status": 500,
"error": "Internal Server Error",
"message": "Type definition error: [simple type, class net.i2p.crypto.eddsa.math.ed25519.Ed25519LittleEndianEncoding]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class net.i2p.crypto.eddsa.math.ed25519.Ed25519LittleEndianEncoding and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: java.util.Collections$UnmodifiableRandomAccessList[0]->........)",
"path": "/api/test"
}
注:这里的堆栈跟踪位于
message
而不是 exception
json的一部分。如您所见,我已经在格式化时间戳:
@Component
public class CustomErrorAttributes extends DefaultErrorAttributes {
private static final DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
private static final String TIMESTAMP = "timestamp";
@Override
public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
//Let Spring handle the error first
Map<String, Object> errorAttributes = super.getErrorAttributes(webRequest, includeStackTrace);
//Format & update timestamp
Object timestamp = errorAttributes.get(TIMESTAMP);
if(timestamp == null) {
errorAttributes.put(TIMESTAMP, dateFormat.format(new Date()));
} else {
errorAttributes.put(TIMESTAMP, dateFormat.format((Date)timestamp));
}
return errorAttributes;
}
}
但我也需要处理消息。
如果这 500 是我能做的唯一错误:
errorAttributes.put("message", "Server error. Contact support.");
但是,所有错误都会在这里发生,这将覆盖所有消息。
我可以检查状态是否为 500,然后才修改它。但是,可能会生成其他错误,这些错误也可能泄漏堆栈跟踪。
使用
@RestControllerAdvice
似乎需要知道生成的每个异常并具有 @ExceptionHandler
对于每个人,并且知道要响应哪个状态代码。有没有更清洁的方法来处理这个?
最佳答案
这可能不是“最干净”的方法,但在我参与的项目中,我们对跨项目的错误响应有一个“标准格式”,所以我们有一个自定义对象,其字段与我们的 orgs 标准(HttpStatus、Reason等)扩展了 RuntimeException。然后在我们的 Controller 、服务、存储库等中,我们将捕获异常并相应地创建此对象,然后抛出自定义对象。根据它在应用程序中发生的位置(repo、服务、 Controller 等),我们可以给它自己的自定义措辞,但仍然在我们的服务器日志中注销完整的异常,以便我们稍后进行调查
例如,如果我们在存储库中发现错误,我们将创建自定义错误对象,将原因设置为 DB 不可用(实际上所有消费者都需要知道),将状态设置为 HttpStatus.SERVICE_UNAVAILABLE(我们使用原因和 httpstatus 跟踪这些枚举以保持跨模块的状态相同),并将自定义对象扔到要返回的 Controller 上。
抱歉,如果这是一个冗长的答案,可能无法给你想要的东西,我不太熟悉你是如何尝试这样做的,所以我只想举一个其他方法的例子。我也会放一些示例代码
自定义异常(exception):
data class MyException(
val reason: String,
val httpStatus: HttpStatus? = null
) : RuntimeException(reason)
创建方法:
fun createApiException(errorCode: ErrorCodeEnum) = MyException(
reason = errorCode.reason,
httpStatus = errorCode.httpStatus,
)
关于rest - 自定义 Spring Boot 异常处理以防止在 Rest 响应中返回 Stacktraces,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55941734/