«415 неподдерживаемый тип носителя» для типа контента «application / csp-report» в ASP. NET Core - PullRequest
5 голосов
/ 19 января 2020

У меня есть политика безопасности содержимого, которая заставляет Chrome опубликовать отчет, но действие, которое получает отчет, возвращает «415 Unsupported Media Type». Я понимаю, что это потому, что пост имеет тип контента "application / csp-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; }
}

Ответы [ 3 ]

4 голосов
/ 19 января 2020

В следующем примере показано, как добавить поддержку SystemTextJsonInputFormatter для обработки дополнительных типов носителей:

services.AddControllers(options =>
{
    var jsonInputFormatter = options.InputFormatters
        .OfType<SystemTextJsonInputFormatter>()
        .Single();

    jsonInputFormatter.SupportedMediaTypes.Add("application/csp-report");
});

Это двухэтапный процесс:

  1. Опрос настроенный список форматеров ввода для поиска SystemTextJsonInputFormatter.
  2. Добавить 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");
})

Есть Два небольших различия:

  1. Тип NewtonsoftJsonInputFormatter вместо SystemTextJsonInputFormatter.
  2. В коллекции два экземпляра этого типа, поэтому мы выберите первый (см. этот ответ для уточнения).

См. Формат входных данных в ASP. NET Базовых документах чтобы узнать больше о них.

1 голос
/ 02 марта 2020

Я хотел бы добавить, что принятое решение не работает для меня. (. NET Core 3.1) У меня точно такой же вариант использования в отношении отчетов CSP. При попытке использовать NewtonSoft и изменении InputFormatter NewtonsoftJsonInputFormatter для приема медиа-заголовка типа application/csp-report, я всегда получал исключение, говоря, что inputformatter не может быть найден (с или без .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 и выбрать правильный на основе маршрута )

0 голосов
/ 23 января 2020

У меня была та же проблема на прошлой неделе, и я нашел альтернативное решение, используя мой собственный пользовательский форматер :

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());
      });
    }

Я sh Я видел решение Кирка Ларкина ранее, поскольку оно, очевидно, является более кратким.

Я полагаю, что решение для пользовательского форматирования полезно, если вы хочу принять типы тел, которые не действительны json хотя.

...