我正在构建一个 REST API,它使用 Spring Security(及其过滤器链)通过 JWT 对用户进行身份验证。现在,如果这样的 JWT 丢失、过期或类似情况,我想向 API 使用者返回格式良好的错误消息,而不是默认的白标错误响应。从 Spring Security 过滤器返回的 API 错误消息应该与业务逻辑失败时返回的错误消息相同。
如果业务逻辑失败,我的 Spring REST 控制器会返回格式如下的错误消息(通过@RestControllerAdvice
):
Content-Type: application/json
{
"code": "VOUCHER_NOT_FOUND",
"message": "The specified voucher code was not found.",
"timestamp": "2020-09-06T21:22:23.015Z"
}
据我所知,如果 Spring Security 过滤器链中发生错误,则永远无法到达控制器,因此我必须从安全过滤器中返回 HTTP 错误消息。我尝试这样做:
public class JwtAuthorizationFilter extends BasicAuthenticationFilter {
@Override
protected final void doFilterInternal(final HttpServletRequest request,
final HttpServletResponse response, final FilterChain chain)
throws IOException, ServletException {
try {
// Perform various auth checks here
// Throw JwtAuthorizationException if a check fails
chain.doFilter(request, response);
} catch (JwtAuthorizationFailedException e) {
response.setStatus(HttpStatus.UNAUTHORIZED.value());
response.setHeader("Content-Type", "application/json"); // does not work
response.getWriter().write("{ \"Simple\": \"Test\" }");
}
}
问题是,我收到的错误消息总是设置不同的Content-Type
标题(带有charset=ISO-8859-1
added):
Content-Type: application/json;charset=ISO-8859-1
{
"Simple": "Test"
}
我想简化这一点并使其保持一致。所以问题是,我怎样才能确保,只有
Content-Type: application/json
是从安全过滤器返回的吗?我尝试过很多选择,比如
response.setHeader("Content-Type", "application/json");
or
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
但所有这些都不起作用。有任何想法吗?