问题
I have a content security policy that causes Chrome to post a report, but the action that receives the report returns "415 Unsupported Media Type". I understand this is because the post has a Content-Type of "application/csp-report". How do I add this as a allowed content type in Core 3.1 (its basically just json).
Action
// https://anthonychu.ca/post/aspnet-core-csp/
[HttpPost][Consumes("application/csp-report")]
public IActionResult Report([FromBody] CspReportRequest request)
{
return Ok();
}
Cut down version of model
public class CspReportRequest
{
[JsonProperty(PropertyName = "csp-report")]
public CspReport CspReport { get; set; }
}
public class CspReport
{
[JsonProperty(PropertyName = "document-uri")]
public string DocumentUri { get; set; }
}
回答1:
The following example shows how to add support to the SystemTextJsonInputFormatter
for handling additional media-types:
services.AddControllers(options =>
{
var jsonInputFormatter = options.InputFormatters
.OfType<SystemTextJsonInputFormatter>()
.Single();
jsonInputFormatter.SupportedMediaTypes.Add("application/csp-report");
});
This is a two-step process:
- Interrogate the configured list of input-formatters to find the
SystemTextJsonInputFormatter
. - Add
application/csp-report
to its existing list of supported media-types (application/json
,text/json
, andapplication/*+json
).
If you're using Json.NET instead of System.Text.Json
, the approach is similar:
services.AddControllers(options =>
{
var jsonInputFormatter = options.InputFormatters
.OfType<NewtonsoftJsonInputFormatter>()
.First();
jsonInputFormatter.SupportedMediaTypes.Add("application/csp-report");
})
There are two small differences:
- The type is
NewtonsoftJsonInputFormatter
instead ofSystemTextJsonInputFormatter
. - There are two instances of this type in the collection, so we target the first (see this answer for the specifics).
See Input Formatters in the ASP.NET Core docs to learn more about those.
回答2:
I would like to add that the accepted solution did not work for me. (.NET Core 3.1) I have the exact same use case regarding the CSP reports. When trying to use NewtonSoft and modifying the InputFormatter NewtonsoftJsonInputFormatter
to accept media header type application/csp-report
, I would always get an exception saying the inputformatter could not be found (with or without .AddNewtonsoftJson();
)
I managed to solve the problem by doing the following:
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);
});
My model and the controller action are the same as the ones posted in the question.
(I derived my solution from How to configure two JSON serializers and select the correct one based on the route)
回答3:
I had the same problem last week and found an alternative solution using my own custom formatter:
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);
}
}
}
Which has to be registered in Startup.cs of course:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers(options =>
{
options.InputFormatters.Insert(0, new CSPReportInputFormatter());
});
}
I wish I had seen Kirk Larkin's solution earlier, as it obviously is more concise.
I suppose the custom formatter solution is helpful, if you want to accept body types that aren't valid json though.
来源:https://stackoverflow.com/questions/59811255/415-unsupported-media-type-for-content-type-application-csp-report-in-asp-ne