MVC - 当内容类型是自定义的(不是应用程序/json)时接受 JSON

Mer*_*ous 5 java model-view-controller json content-security-policy

我正在尝试为我的网站实施 Content-Security-Policy-Report-Only 标头。为了做到这一点,我需要一个控制器来接受浏览器的 POST 请求——它将以 JSON 的形式发送有关违规的数据。然而,这个请求似乎将 Content-Type 指定为application/csp-report而不是application/json(旁注:为什么??)。

这显然导致 Spring 拒绝请求 - 似乎@RequestBody使 spring的用法只接受 Content-Type 的请求"application/json"。即使我专门为它设置了注释的值consumes,它仍然不接受请求。@RequestMappingapplication/csp-report

我已经使用过滤器来包装请求HttpServletRequestWrapper- 这似乎是修改请求行为的常用方法。我已经覆盖了所有这些方法:getContentType(), getHeader(String),getHeaders(String)以返回“application/json”。但是请求仍然没有通过。

  • 我在这里缺少什么?
  • 有没有更好的解决方案不需要我对请求做魔法?
  • 我什至不介意手动解析 JSON,我可以以某种方式接受它作为纯字符串吗?

M. *_*rov 4

根据@RequestBody注释文档,

请求正文通过HttpMessageConverter传递,以根据请求的内容类型解析方法参数

这意味着 Spring Framework 定义了一个专门的 API,用于定义某些 MediaType 在用作 REST 端点的参数时如何转换为某些 Java 类型。

是一篇很好的文章,展示了这些功能。

有大量内置的 Spring 转换器,如果您的媒体格式可以映射到它们各自的媒体格式,您可能只需配置和使用它们即可。针对您的情况,您应该查看spring.converter.json包中可用的转换器之一。在最简单的情况下,使其工作应该简单如下:

HttpMessageConverter converter = new <JsonConverterOfYourChoice>(JsonMapper);

converter.getSupportedMediaTypes().add(new MediaType("application", "csp-report"));
Run Code Online (Sandbox Code Playgroud)

然后像你一样将这样的转换器注册到弹簧的配置中。

其他可用的转换器类型包括:

  • 字符串Http消息转换器
  • ObjectToStringHttpMessageConverter(如果您已经配置了 Spring 的ConversionService以从 String 中读取所需的类型)
  • ByteArrayHttpMessageConverter
  • 表单Http消息转换器
  • spring.converter.xml包中的各种基于 XML 的转换器
  • AllEncompassingFormHttpMessageConverter(基于表单转换器构建的转换器,也能够处理 XML 和 JSON)
  • Protobuf HttpMessageConverter
  • Atom/RSS feed 消息转换器。

最后,如果以上都不适合您,您可以创建并注册您自己的 HttpMessageConverter 实现。