我有一个内容安全策略,导致 Chrome 浏览器发布报告,但接收报告的操作却返回 "415 不支持的媒体类型"。我理解这是因为该帖子的内容类型为 "applicationcsp-report"。我如何将其添加为 Core 3.1 中允许的内容类型(基本上就是 json)。
操作
// https://anthonychu.ca/post/aspnet-core-csp/
[HttpPost][Consumes("application/csp-report")]
public IActionResult Report([FromBody] CspReportRequest request)
{
return Ok();
}
缩小版模型
public class CspReportRequest
{
[JsonProperty(PropertyName = "csp-report")]
public CspReport CspReport { get; set; }
}
public class CspReport
{
[JsonProperty(PropertyName = "document-uri")]
public string DocumentUri { get; set; }
}
下面的示例展示了如何向Chrome浏览器添加支持。SystemTextJsonInputFormatter
用于处理额外的媒体类型。
services.AddControllers(options =>
{
var jsonInputFormatter = options.InputFormatters
.OfType<SystemTextJsonInputFormatter>()
.Single();
jsonInputFormatter.SupportedMediaTypes.Add("application/csp-report");
});
这是一个两步走的过程。
SystemTextJsonInputFormatter
.application/csp-report
到其现有支持的媒体类型列表中(application/json
, text/json
和 application/*+json
).如果你使用的是Json.NET而不是 System.Text.Json
办法是 类似:
services.AddControllers(options =>
{
var jsonInputFormatter = options.InputFormatters
.OfType<NewtonsoftJsonInputFormatter>()
.First();
jsonInputFormatter.SupportedMediaTypes.Add("application/csp-report");
})
有两个小区别。
NewtonsoftJsonInputFormatter
而不是 SystemTextJsonInputFormatter
.详见 输入格式 在ASP.NET Core文档中了解更多关于这些的信息。
我想补充的是,被接受的解决方案对我不起作用。(.NET Core 3.1)我有一个关于CSP报告的完全相同的用例。当试图使用NewtonSoft并修改InputFormatter时 NewtonsoftJsonInputFormatter
接受媒体头类型 application/csp-report
我总是会得到一个异常,说找不到输入格式(不管有没有使用 .AddNewtonsoftJson();
)
我通过以下方法解决了这个问题。
services.AddControllers().AddNewtonsoftJson();
services.AddOptions<MvcOptions>()
.PostConfigure<IOptions<JsonOptions>, IOptions<MvcNewtonsoftJsonOptions>, ArrayPool<char>, ObjectPoolProvider, ILoggerFactory>(
(mvcOptions, jsonOpts, newtonJsonOpts, charPool, objectPoolProvider, loggerFactory) =>
{
var formatter = mvcOptions.InputFormatters.OfType<NewtonsoftJsonInputFormatter>().First(i => i.SupportedMediaTypes.Contains("application/json"));
formatter.SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/csp-report"));
mvcOptions.InputFormatters.RemoveType<NewtonsoftJsonInputFormatter>();
mvcOptions.InputFormatters.Add(formatter);
});
我的模型和控制器的动作与问题中的相同。
我的解决方案来自于 如何配置两个JSON序列器,并根据路由选择正确的序列器。)
上周我也遇到了同样的问题,我找到了一个替代的解决方案,使用我自己的 自定义格式器:
using CspReportLogger.Models;
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.Net.Http.Headers;
using System;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
namespace CspReportLogger.Formatters
{
public class CSPReportInputFormatter : TextInputFormatter
{
public CSPReportInputFormatter()
{
// Specify the custom media type.
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/csp-report"));
SupportedEncodings.Add(Encoding.UTF8);
}
public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context, Encoding effectiveEncoding)
{
// Deserialize the body using our models and the JsonSerializer.
CspReportRequest report = await JsonSerializer.DeserializeAsync<CspReportRequest>(context.HttpContext.Request.Body);
return await InputFormatterResult.SuccessAsync(report);
}
}
}
当然要在Startup.cs中注册。
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers(options =>
{
options.InputFormatters.Insert(0, new CSPReportInputFormatter());
});
}
我希望我已经看到 Kirk Larkin的解决方案 因为它显然更简洁。
我想,如果你想接受不是有效的json的body类型,不过自定义formatter的解决方案是有帮助的。