Почему я получаю ошибки CORS при запуске этого метода PATCH из React в WebAPI?

Итак, вот мой код инициализации Cors:

        app.UseCors(builder =>
            builder.AllowAnyMethod().AllowAnyHeader().AllowAnyOrigin());

И все же, когда я запускаю PATCH, я получаю следующую ошибку в Chrome 83:

Доступ к выборке на https://api-dev.myproject.com/api/mp из источника https://users-dev.myproject.com заблокирован политикой CORS: нет «Access-Control-Allow». Заголовок -Origin присутствует на запрошенном ресурсе. Если непрозрачный ответ соответствует вашим потребностям, установите для режима запроса значение «no-cors», чтобы получить ресурс с отключенным CORS.

Вот код, который вызывает API (из React):

  const response = await fetch(API_URL() + `/mp`, {
    method: 'PATCH',
    body: `"${JSON.stringify(mpForm.values)}"`,
    headers: {
      Authorization: 'Bearer ' + apiToken,
      'Content-type': 'application/json'
    }
  });

Что здесь может быть не так? Большинство запросов API к этому домену выполняются нормально. На данный момент только этот.

ОБНОВЛЕНИЕ

На всякий случай, если вы столкнулись именно с этой проблемой, основной причиной этой проблемы была строка тела:

body: `"${JSON.stringify(mpForm.values)}"`,

и проблема была решена путем рефакторинга API для работы с телом, подобным этому:

body: JSON.stringify(mpForm.values),

Причина, по которой это было проблемой, заключалась в том, что функция stringify заключала в возвращаемое значение двойные кавычки, в результате чего передавалась такая строка:

'"{"foo":"bar"}"'

что затем вызвало ошибку CORS.


person dylanT    schedule 17.07.2020    source источник
comment
Покажите трассировку этого запроса в Chrome и трассировку аналогичного запроса к тому же API, который работает. Мы хотим посмотреть заголовки и конкретный запрос, который не удался и вызвал отказ.   -  person Chris Schaller    schedule 17.07.2020
comment
Посмотрите на ответ на запрос OPTIONS, найдите источник разрешения, соответствующий вашему вызывающему сайту. Если этого нет, поищите другой конфликтующий конфиг в вашем API.   -  person Chris Schaller    schedule 17.07.2020
comment
Пожалуйста, обновите тег, чтобы отразить, является ли это ASP.Net или ядром?   -  person Chris Schaller    schedule 17.07.2020
comment
@ChrisSchaller спасибо за ваши вопросы. Теперь это решено, поэтому, к сожалению, я не могу воспроизвести следы. Однако проблема возникла из-за неправильно сформированного тела запроса.   -  person dylanT    schedule 17.07.2020


Ответы (3)


Ваша конфигурация CORS выглядит правильной, если некоторые запросы работают, а другие нет, то есть вероятность, что проблема вообще не в API.

  1. #P2#
    app.UseCors(builder => builder
       .AllowAnyOrigin()
       .AllowAnyMethod()
       .AllowAnyHeader()
    
    <цитата> #P3#
  2. Убедитесь, что в вашем API нет конфликтующей конфигурации CORS, найдите индивидуальную конфигурацию CORS в контроллерах или методах для запроса, который не работает.

  3. #P5# <блочная цитата> #P6#

Обновлять:

Проблема OP вообще не была связана напрямую с CORS, однако это хорошее напоминание о двух важных уроках:

  1. Неправильно сформированные запросы веб-API могут дать сбой до создания правильного ответа на запрос OPTIONS, и если запрос OPTIONS не отвечает в соответствии со спецификацией, браузер сначала сообщит об этом как о проблеме отказа CORS, подавляя реальный ошибочный ответ от API.

  2. При размещении вопросов на форумах для получения рекомендаций по устранению ошибок предоставление кода, вызывающего ошибки, лишь рисует часть картины. Вам необходимо включить журналы, которые показывают значения времени выполнения, а также фактическое сообщение об ошибке.

  • Для отладки любых проблем веб-API между клиентом и сервером вы всегда должны смотреть на фактический контент HTTP-запроса и ответа и заголовки для затронутого вызова, вы можете увидеть сетевую трассировку с помощью инструментов разработчика вашего браузера, однако если вам нужно регулярно отлаживать подобные проблемы в рабочей среде, вам следует рассмотреть возможность ведения журнала трассировки запросов либо на стороне клиента, либо на стороне сервера.
person Chris Schaller    schedule 17.07.2020
comment
Я не верю, что это сработает, поскольку вы не должны комбинировать AllowAnyOrigin с AllowCredentials. - person dylanT; 17.07.2020
comment
Спасибо, @dylanT, ты не должен, но это не значит, что ты не можешь. Ключевым моментом здесь, который я упустил из виду, является то, что он терпит неудачу только по одному конкретному запросу. Я предположил, что это был единственный запрос, в котором вы использовали аутентификацию, но это было глупое предположение. Сейчас я полностью изменил свой ответ, но полезно помнить, что это распространенный сценарий в веб-API и разработке клиентов. Не смотрите на CORS как на проблему просто потому, что браузер считает проблему. - person Chris Schaller; 18.07.2020
comment
Спасибо за подробное обновление. Я отмечу ваш ответ как правильный, так как в нем есть несколько полезных советов. - person dylanT; 20.07.2020

Вы не можете сочетать «разрешить любое происхождение» с авторизацией. Это угроза безопасности. Вместо того, чтобы разрешать любой источник, вы можете повторить источник запроса, хотя вы должны знать, что это создает некоторый риск для безопасности — вы разрешаете токены аутентификации из любого домена. Лучше правильно настроить CORS с разрешенными доменами.

См. принятый ответ на этот вопрос: C# WEB API CORS не работает для одного из способов настроить серверную часть в этом сценарии, избегая использования Access-Control-Allow-Origin:*.

person see sharper    schedule 17.07.2020
comment
Я ценю это. Я просто пытаюсь заставить его работать в простейшем случае. Считаете ли вы, что разрешение любого происхождения является причиной ошибки? - person dylanT; 17.07.2020
comment
Это действительно вообще не решает проблему ОП. - person Chris Schaller; 17.07.2020
comment
@dylanT Да. Я не просто говорю вам об угрозе безопасности. Я говорю, что браузер не позволит этого. - person see sharper; 17.07.2020
comment
@КрисШаллер? Браузеры не будут разрешать запросы с учетными данными с любым источником. - person see sharper; 17.07.2020
comment
@seesharper В коде мы говорим «Разрешить любой», но реализация во время выполнения фактически возвращает хост вызывающей стороны, а не *, код OP должен делать это правильно, если нет конфликтующих конфигураций. - person Chris Schaller; 17.07.2020
comment
Вы уверены, что @ChrisSchaller? Я вижу это в документах: Specifying AllowAnyOrigin and AllowCredentials is an insecure configuration and can result in cross-site request forgery. The CORS service returns an invalid CORS response when an app is configured with both methods. - person see sharper; 17.07.2020
comment
Относительно: docs.microsoft.com/en-us/aspnet/core/security/ это может быть верно для [asp.net-core], но отлично работает в .Net FX, я не заметил никаких проблем в моих API но когда мы развертываем на живых хостах, мы настраиваем явное происхождение. - person Chris Schaller; 17.07.2020

После долгих поисков и устранения неполадок мы смогли определить, что основной причиной проблемы было тело запроса. Метод stringify заключал двойные кавычки в строку, заключенную в двойные кавычки.

Почему это вызвало ошибку CORS, мне остается неясным, но, скорее всего, это отвлекающий маневр.

Починка кузова решила проблему.

Мне было бы интересно понять цепочку событий, которая привела к ошибке CORS в браузере. Но в остальном мы решили это.

person dylanT    schedule 17.07.2020