Spring端点如何禁用默认Accept头*/* 拒绝无该头请求
问题原因
Spring 默认将缺失的 Accept 请求头解析为 */*(即 MediaType.ALL)是符合 HTTP/1.1 规范(RFC7231)的行为:规范明确说明客户端未携带 Accept 头时,默认视为客户端接受所有响应媒体类型。Spring 没有提供直接关闭该默认填充逻辑的配置项,因为默认行为本身是遵循标准的。
注意:如果你直接在接口参数中绑定 MediaType 类型的 Accept 头,Spring 会在参数解析阶段提前完成默认值填充,此时你无法区分请求是真的携带了Accept: */*头,还是根本没带头被框架补了默认值。
可行方案
方案1:接口内单独校验(适合少量接口需要该规则的场景)
不要直接绑定 MediaType 类型参数,先接收原始字符串类型的头值判断是否存在,再自行解析媒体类型:
@GetMapping("/") public void get(@RequestHeader(value = HttpHeaders.ACCEPT, required = false) String rawAccept) { if (rawAccept == null || rawAccept.isBlank()) { throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "请求必须携带Accept请求头"); } MediaType accept = MediaType.parseMediaType(rawAccept); // 后续业务逻辑 }
直接从请求中取原始字符串头时,未携带头的情况会返回null,不会被框架提前填充默认值,能准确判断头是否真实存在。
方案2:全局拦截器校验(适合所有/大部分接口需要该规则的场景)
自定义Spring MVC拦截器,在请求进入控制器之前统一校验Accept头的存在性,不需要在每个接口重复写校验逻辑:
- 编写拦截器实现
@Component public class MandatoryAcceptHeaderInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String acceptHeader = request.getHeader(HttpHeaders.ACCEPT); if (acceptHeader == null || acceptHeader.trim().isEmpty()) { response.sendError(HttpServletResponse.SC_BAD_REQUEST, "缺失必填请求头:Accept"); return false; } return true; } }
- 注册拦截器到Spring MVC配置中
@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Resource private MandatoryAcceptHeaderInterceptor acceptHeaderInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(acceptHeaderInterceptor) .addPathPatterns("/**"); // 按需调整需要拦截的路径范围 } }
避坑提示
不要尝试通过修改ContentNegotiationManager的默认媒体类型实现需求:这种方式依然会在头缺失时填充你设置的默认值,你依然无法区分“客户端主动传了对应类型的Accept头”和“客户端没带头被框架补了默认值”的场景,无法实现“没带头就拒绝”的需求。
内容的提问来源于stack exchange,提问作者membersound
相关产品推荐
相关产品推荐

