SpringBoot 2.0迁移后无法获取后端HTTP Servlet响应求助
看起来你在从Spring Boot 1.5.1迁移到2.0.0.RELEASE后,原本用来拦截非法登录请求的AuthenticationEntryPoint#commence方法出现了响应不符合预期的情况——在1.5.x版本里调用response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage())能正常向前端返回带错误信息的401响应,但升级后要么错误信息丢失,要么响应格式被Spring Boot的默认逻辑改写了对吧?
这是因为Spring Boot 2.0在错误处理机制上做了不少调整,尤其是默认的ErrorMvcAutoConfiguration和Spring Security的响应处理逻辑有了变化。下面给你几个可行的解决方案:
方案一:手动构造JSON响应(最直接)
放弃使用sendError方法,直接通过响应流输出自定义的JSON内容,这样可以绕过Spring Boot的默认错误处理器,确保你的错误信息能直接返回给前端。示例代码如下:
@Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException { // 设置响应状态码 response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // 设置响应内容类型为JSON response.setContentType("application/json;charset=UTF-8"); // 构造错误响应体 String errorJson = String.format("{\"code\": %d, \"message\": \"%s\"}", HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage()); // 写入响应流 response.getWriter().write(errorJson); response.getWriter().flush(); }
方案二:配置Spring Boot的错误处理参数
如果还是想保留sendError的调用方式,可以通过配置Spring Boot的错误处理属性,让默认的错误响应包含自定义的错误信息。在application.properties或application.yml中添加以下配置:
application.properties
# 允许在错误响应中包含异常信息 server.error.include-message=always # 可选:关闭栈信息返回(根据业务需求调整) server.error.include-stacktrace=never
application.yml
server: error: include-message: always include-stacktrace: never
配置后,Spring Boot的默认错误响应会包含你传入的authException.getMessage()内容,响应格式大概是这样:
{ "timestamp": "2024-05-20T10:00:00.000+00:00", "status": 401, "error": "Unauthorized", "message": "你的错误信息", "path": "/your-request-path" }
方案三:自定义ErrorAttributes(更灵活)
如果需要完全控制错误响应的格式,可以自定义ErrorAttributes来覆盖默认的行为。创建一个类继承DefaultErrorAttributes:
@Component public class CustomErrorAttributes extends DefaultErrorAttributes { @Override public Map<String, Object> getErrorAttributes(WebRequest webRequest, ErrorAttributeOptions options) { // 获取默认的错误属性 Map<String, Object> errorAttributes = super.getErrorAttributes(webRequest, options); // 修改或添加自定义属性 errorAttributes.put("customCode", errorAttributes.get("status")); errorAttributes.put("customMsg", errorAttributes.get("message")); // 移除不需要的默认属性 errorAttributes.remove("timestamp"); errorAttributes.remove("path"); return errorAttributes; } }
这样无论你是通过sendError还是其他方式触发错误,最终的响应格式都会按照你自定义的规则生成。
内容的提问来源于stack exchange,提问作者Bryan.xiang

