RestAssured调用Spring认证接口时请求体为空导致401问题
我之前也踩过一模一样的坑!结合你的描述——RestAssured发的POST JSON请求明明已经通过ngrep确认发送成功,但Spring拦截器里拿到的请求体是空,用curl/Postman却完全正常,大概率是以下几个原因之一,给你逐个排查的方向:
1. 确认RestAssured的请求体构建是否正确
很多时候是因为没正确使用body()方法传参,比如误用了params()(这是传表单参数的)。正确的JSON请求写法应该是:
// 方式1:直接传序列化后的JSON字符串 given() .contentType(ContentType.JSON) .body("{\"username\":\"test\",\"password\":\"123456\"}") .when() .post("/api/auth") .then() .log().all(); // 方式2:传Java对象,让RestAssured自动序列化(依赖Jackson) AuthRequestDto authRequest = new AuthRequestDto("test", "123456"); given() .contentType(ContentType.JSON) .body(authRequest) .when() .post("/api/auth") .then() .log().all();
如果是用对象序列化,要确保项目里有jackson-databind依赖,并且RestAssured能自动识别到它(最新版本的RestAssured默认集成Jackson,但如果依赖冲突可能会失效)。
2. 检查Spring拦截器/过滤器的请求体读取逻辑
HTTP请求体只能被读取一次,如果你的认证拦截器/过滤器在Spring解析@RequestBody之前,直接用request.getInputStream()或request.getReader()读取了请求体,那后续Spring就拿不到数据了。
解决办法是用Spring提供的ContentCachingRequestWrapper包装请求,它会把请求体缓存起来,支持重复读取:
public class AuthFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { // 包装请求,缓存请求体 ContentCachingRequestWrapper cachedRequest = new ContentCachingRequestWrapper(request); // 这里读取缓存的请求体做认证逻辑 byte[] requestBody = cachedRequest.getContentAsByteArray(); if (requestBody.length > 0) { String bodyStr = new String(requestBody, cachedRequest.getCharacterEncoding()); // 处理认证逻辑 } // 用包装后的请求继续传递 filterChain.doFilter(cachedRequest, response); } }
记得在Spring配置里注册这个过滤器,替换原来的直接读取请求体的逻辑。
3. 排查RestAssured的全局配置是否覆盖了请求头
有时候全局配置会意外覆盖请求的contentType设置,比如不小心设置了:
RestAssured.defaultParser = Parser.TEXT;
这会导致RestAssured默认不按JSON解析请求体。解决办法是在单个请求里显式指定contentType和accept:
given() .contentType(ContentType.JSON) .accept(ContentType.JSON) .body(authRequest) .when() .post("/api/auth")
4. 检查Spring的消息转换器配置
如果你的Spring项目自定义了HttpMessageConverter,要确保MappingJackson2HttpMessageConverter没有被移除,它是Spring解析JSON请求体的核心转换器。可以在配置类里确认:
@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { // 不要移除默认的Jackson转换器,或者手动添加 converters.add(new MappingJackson2HttpMessageConverter()); // 其他自定义转换器... } }
最后可以加个调试小技巧:在Spring的拦截器里打印请求的Content-Type头和缓存的请求体,确认请求头是否正确,以及请求体是否真的为空——有时候只是读取方式不对,不是真的没收到。
内容的提问来源于stack exchange,提问作者mik3fly-4steri5k

