Почему мой код JavaScript получает ошибку «Нет заголовка Access-Control-Allow-Origin» в запрошенном ресурсе », а Postman - нет?

avatar
Mr Jedi
17 ноября 2013 в 19:29
5176198
11
2906

Mod note : этот вопрос о том, почему XMLHttpRequest / fetch и т. Д. в браузере подчиняются ограничениям одной и той же политики доступа (вы получаете ошибки с упоминанием CORB или CORS), в то время как Postman - нет. Это вопрос , а не о том, как исправить ошибку «No 'Access-Control-Allow-Origin' ...». Это о том, почему они происходят.

Пожалуйста, прекратите публикацию :

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

Я пытаюсь выполнить авторизацию с использованием JavaScript, подключившись к RESTful API встроенный <2589248 Однако когда я делаю запрос, я получаю следующую ошибку:

XMLHttpRequest не может загрузить http: // myApiUrl / login. На запрошенном ресурсе отсутствует заголовок Access-Control-Allow-Origin. Следовательно, к источнику 'null' доступ запрещен.

Я знаю, что API или удаленный ресурс должен устанавливать заголовок, но почему это сработало, когда я сделал запрос через расширение Chrome Postman?

Это код запроса:

$.ajax({
    type: "POST",
    dataType: 'text',
    url: api,
    username: 'user',
    password: 'pass',
    crossDomain : true,
    xhrFields: {
        withCredentials: true
    }
})
    .done(function( data ) {
        console.log("done");
    })
    .fail( function(xhr, textStatus, errorThrown) {
        alert(xhr.responseText);
        alert(textStatus);
    });
Источник
MD. Sahib Bin Mahboob
17 ноября 2013 в 19:31
43

Вы выполняете запрос с localhost или напрямую выполняете HTML?

Mr Jedi
17 ноября 2013 в 19:43
2

@ MD.SahibBinMahboob Если я понимаю ваш вопрос, я делаю запрос с localhost - у меня есть страница на моем компьютере, и я просто запускаю ее. Когда я разворачиваю сайт на хостинге, результат такой же.

MD. Sahib Bin Mahboob
17 ноября 2013 в 19:47
0

одинаковый или разный домен вашей исполняемой страницы и запрошенное доменное имя?

Sam Eaton
18 июня 2015 в 15:22
12

Для тех, кто хочет больше читать, в MDN есть хорошая статья о запросах ajax и cross origin: developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

Peter Mortensen
4 октября 2021 в 09:50
0

Ответ на этот вопрос (теперь удаленный и видимый только для 10K) является предметом мета-вопроса Почему этот ответ, за который проголосовали, был удален один раз и снова удален при повторном размещении?

Ответы (11)

avatar
MD. Sahib Bin Mahboob
17 ноября 2013 в 19:49
1515

Если я правильно понял, вы выполняете XMLHttpRequest в другом домене, чем ваша страница. Таким образом, браузер блокирует его, поскольку он обычно разрешает запрос в том же источнике по соображениям безопасности. Вам нужно сделать что-то другое, если вы хотите выполнить междоменный запрос. Учебное пособие о том, как этого добиться: Использование CORS .

Когда вы используете Postman, они не ограничиваются этой политикой. Цитируется из Cross-Origin XMLHttpRequest :

Обычные веб-страницы могут использовать объект XMLHttpRequest для отправки и получения данных с удаленных серверов, но они ограничены одной и той же политикой происхождения. Расширения не так уж ограничены. Расширение может взаимодействовать с удаленными серверами за пределами своего источника, если оно сначала запрашивает разрешения на разные источники.

Ray Nicholus
17 ноября 2013 в 20:01
213

Браузер не блокирует запрос. Единственные браузеры, которые полностью блокируют запросы AJAX из разных источников, - это IE7 или более ранние версии. Все браузеры, кроме IE7 и старше, реализуют спецификацию CORS (IE8 и IE9 частично). Все, что вам нужно сделать, это согласиться на запросы CORS на вашем сервере API, вернув правильные заголовки на основе запроса. Вы должны прочитать о концепциях CORS на mzl.la/VOFrSz. Почтальон также отправляет запросы через XHR. Если вы не видите такой же проблемы при использовании почтальона, это означает, что вы неосознанно не отправляете тот же запрос через почтальона.

Ray Nicholus
17 ноября 2013 в 20:08
15

@ MD.SahibBinMahboob Почтальон НЕ отправляет запрос "из вашего кода java / python". Он отправляет запрос прямо из браузера. XHR в расширениях Chrome работает немного по-другому, особенно когда задействованы запросы от разных источников.

avatar
lunarzshine
13 апреля 2022 в 19:35
0

Чтобы решить эту проблему, напишите эту строку кода в вашей функции doGet() или doPost() в зависимости от того, что вы используете в бэкенде. response.setHeader("Access-Control-Allow-Origin", "*");

avatar
Bapan Biswas
14 февраля 2022 в 01:29
0

Ваш IP-адрес не внесен в белый список, поэтому вы получаете эту ошибку. Попросите обслуживающий персонал внести ваш IP-адрес в белый список для службы, к которой вы обращаетесь. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers

avatar
Daniel Iftimie
10 января 2022 в 12:28
0

Для тестирования браузера: Windows — выполнить:

chrome.exe --user-data-dir="C://Chrome dev session" --disable-web-security
avatar
Stas Sorokin
3 января 2022 в 11:36
1

Происхождение решений и проблем

Вы отправляете XMLHttpRequest в разные домены, например:

  1. Домен 1: some-domain.com
  2. Домен два: some-different-domain.com

Эта разница в доменных именах триггеры CORS (Политика ресурсов перекрестного происхождения) Политика под названием SOP (Политика связи) который обеспечивает использование одних и тех же доменов (отсюда Origin) в Ajax, XMLHttpRequest и других HTTP-запросах.

Почему это сработало, когда я сделал запрос через расширение Chrome Почтальон?

Клиент (большинство Браузеров и Средств разработки) может применить политику того же происхождения.

Большинство браузеров обеспечивают политику политики однообразного происхождения для предотвращения вопросов, связанных с CSRF (Запрос на перекрестную площадку) Attack.

Postman как средство разработки предпочитает не применять SOP, в то время как некоторые браузеры применяют его, поэтому вы можете отправлять запросы через Postman, которые вы не можете отправить с помощью XMLHttpRequest через JS с помощью браузера.

avatar
NDM
9 декабря 2021 в 12:34
1

Вы также можете получить эту ошибку, если тайм-аут вашего шлюза слишком мал и ресурс, к которому вы обращаетесь, требует больше времени для обработки, чем тайм-аут. Это может иметь место для сложных запросов к базе данных и т. Д. Таким образом, приведенный выше код ошибки может скрыть эту проблему. Просто проверьте, является ли код ошибки 504 вместо 404, как в ответе Камилса выше, или что-то еще. Если это 504, то увеличение тайм-аута шлюза может решить проблему.

В моем случае ошибку CORS можно было удалить, отключив ту же политику происхождения (CORS) в браузере IE, см. Как отключить такую ​​же политику происхождения в Internet Explorer. После этого в журнале была чистая ошибка 504.

Mr Jedi
9 декабря 2021 в 19:45
0

Если вы получите тайм-аут, вы не получите ошибку CORS

NDM
12 декабря 2021 в 16:49
0

Что ж, я справился с устранением неполадок в системе, и ошибка CORS сбила меня с толку, так как это был слишком короткий тайм-аут, который привел к закрытому соединению. После увеличения тайм-аута система работала отлично. Итак, да, тайм-аут вызвал ошибку No 'Access-Control-Allow-Origin', которая в первую очередь ввела меня в этот поток. Так что это может быть полезно для других, использующих это вместе с 504.

Mr Jedi
14 декабря 2021 в 20:49
0

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

avatar
JacquesB
9 января 2021 в 21:37
21

Вы получаете ошибку из-за стандарта CORS, который устанавливает некоторые ограничения на то, как JavaScript может выполнять запросы ajax.

Стандарт CORS - это стандарт на стороне клиента, реализованный в браузере. Таким образом, именно браузер препятствует завершению вызова и генерирует сообщение об ошибке, а не сервер.

Почтальон не реализует ограничения CORS, поэтому вы не видите ту же ошибку при выполнении того же вызова от Почтальона.

Почему не использует CORS в Postman? CORS определяет ограничения относительно источника (домена URL) страницы, которая инициирует запрос. Но в Postman запросы исходят не со страницы с URL-адресом, поэтому CORS не применяется.

JacquesB
11 января 2021 в 10:24
6

@MrJedi: Принятый ответ не объясняет, почему запрос успешно выполняется в Postman, что и было первоначальным вопросом.

avatar
Gopinath
2 февраля 2020 в 10:27
25

Применение ограничения CORS - это функция безопасности, определяемая сервером и реализуемая браузером .

Браузер просматривает политику CORS сервера и уважает ее.

Однако инструмент Postman не заботится о политике CORS сервера.

Вот почему ошибка CORS появляется в браузере, а не в Postman.

avatar
Kamil Kiełczewski
16 декабря 2019 в 09:06
32

В приведенном ниже исследовании в качестве API я использую http://example.com вместо http: // myApiUrl / login из вашего вопроса, потому что этот первый работает.

Я предполагаю, что ваша страница находится на http: //my-site.local: 8088.

Причина, по которой вы видите разные результаты, заключается в том, что Почтальон:

  • установить заголовок Host=example.com (ваш API)
  • НЕ установлен заголовок Origin

Это похоже на способ отправки запросов браузерами, когда сайт и API имеют один и тот же домен (браузеры также устанавливают элемент заголовка Referer=http://my-site.local:8088, однако я не вижу его в Postman). Когда заголовок Origin не установлен , обычно серверы разрешают такие запросы по умолчанию.

Enter image description here

Это стандартный способ отправки запросов Postman. Но браузер отправляет запросы по-разному, когда ваш сайт и API имеют разные домены , а затем возникает CORS и браузер автоматически:

  • устанавливает заголовок Host=example.com (ваш как API)
  • устанавливает заголовок Origin=http://my-site.local:8088 (ваш сайт)

(заголовок Referer имеет то же значение, что и Origin). И теперь на вкладке Chrome Консоль и сети вы увидите:

Enter image description here

Enter image description here

Когда у вас Host != Origin , это CORS, и когда сервер обнаруживает такой запрос, он обычно блокирует его по умолчанию .

.

Origin=null устанавливается, когда вы открываете HTML-контент из локального каталога и отправляет запрос. Такая же ситуация возникает, когда вы отправляете запрос внутри <iframe>, как в приведенном ниже фрагменте (но здесь заголовок Host вообще не установлен) - в общем, везде, где в спецификации HTML указано непрозрачное происхождение, вы можете перевести это на Origin=null. Более подробную информацию об этом вы можете найти здесь.

fetch('http://example.com/api', {method: 'POST'});
Look on chrome-console > network tab

Если вы не используете простой запрос CORS, обычно браузер автоматически также отправляет запрос OPTIONS перед отправкой основного запроса - дополнительная информация здесь. Во фрагменте ниже это показано:

fetch('http://example.com/api', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json'}
});
Look in chrome-console -> network tab to 'api' request.
This is the OPTIONS request (the server does not allow sending a POST request)

Вы можете изменить конфигурацию своего сервера, чтобы разрешить запросы CORS.

Вот пример конфигурации, которая включает CORS на nginx (файл nginx.conf) - будьте очень осторожны с настройкой always/"$http_origin" для nginx и "*" для Apache - это разблокирует CORS из любого домен.

location ~ ^/index\.php(/|$) {
   ...
    add_header 'Access-Control-Allow-Origin' "$http_origin" always;
    add_header 'Access-Control-Allow-Credentials' 'true' always;
    if ($request_method = OPTIONS) {
        add_header 'Access-Control-Allow-Origin' "$http_origin"; # DO NOT remove THIS LINES (doubled with outside 'if' above)
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Max-Age' 1728000; # cache preflight value for 20 days
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'My-First-Header,My-Second-Header,Authorization,Content-Type,Accept,Origin';
        add_header 'Content-Length' 0;
        add_header 'Content-Type' 'text/plain charset=UTF-8';
        return 204;
    }
}

Вот пример конфигурации, которая включает CORS на Apache (файл .htaccess)

# ------------------------------------------------------------------------------
# | Cross-domain Ajax requests                                                 |
# ------------------------------------------------------------------------------

# Enable cross-origin Ajax requests.
# http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity
# http://enable-cors.org/

# <IfModule mod_headers.c>
#    Header set Access-Control-Allow-Origin "*"
# </IfModule>

# Header set Header set Access-Control-Allow-Origin "*"
# Header always set Access-Control-Allow-Credentials "true"

Access-Control-Allow-Origin "http://your-page.com:80"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header always set Access-Control-Allow-Headers "My-First-Header,My-Second-Header,Authorization, content-type, csrf-token"
avatar
George Livingston
13 декабря 2016 в 13:02
86

Потому что
$ .ajax ({type: "POST" - вызывает ОПЦИИ
- $ .143600> - $ .143600> ЗАПИСЬ

Оба разные. Почтальон правильно называет "POST", но когда мы его вызываем, это будет "OPTIONS".

Для веб-служб C # - Веб-API

Добавьте следующий код в файл web.config в теге <system.webServer>. Это будет работать:

<httpProtocol>
    <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
    </customHeaders>
</httpProtocol>

Убедитесь, что вы не делаете ошибок при вызове Ajax

jQuery

$.ajax({
    url: 'http://mysite.microsoft.sample.xyz.com/api/mycall',
    headers: {
        'Content-Type': 'application/x-www-form-urlencoded'
    },
    type: "POST", /* or type:"GET" or type:"PUT" */
    dataType: "json",
    data: {
    },
    success: function (result) {
        console.log(result);
    },
    error: function () {
        console.log("error");
    }
});

Примечание: Если вы хотите загрузить контент со стороннего веб-сайта , то это не поможет вам . Вы можете попробовать следующий код, но не JavaScript.

System.Net.WebClient wc = new System.Net.WebClient();
string str = wc.DownloadString("http://mysite.microsoft.sample.xyz.com/api/mycall");
avatar
Shady Mohamed Sherif
3 декабря 2014 в 20:24
308

ПРЕДУПРЕЖДЕНИЕ: Использование Access-Control-Allow-Origin: * может сделать ваш API / веб-сайт уязвимым для подделки межсайтовых запросов (CSRF). Убедитесь, что вы понимаете риски, прежде чем использовать этот код.

Это очень просто решить, если вы используете PHP. Просто добавьте следующий скрипт в начало вашей PHP-страницы, который обрабатывает запрос:

<?php header('Access-Control-Allow-Origin: *'); ?>

Если вы используете Node-red, вы должны разрешить CORS в файле node-red/settings.js, не комментируя следующие строки:

// The following property can be used to configure cross-origin resource sharing
// in the HTTP nodes.
// See https://github.com/troygoode/node-cors#configuration-options for
// details on its contents. The following is a basic permissive set of options:
httpNodeCors: {
 origin: "*",
 methods: "GET,PUT,POST,DELETE"
},

Если вы используете Flask, то же, что и в вопросе; сначала нужно установить flask-cors

$ pip install -U flask-cors

Затем включите Flask cors в свое приложение.

from flask_cors import CORS

Простое приложение будет выглядеть так:

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

@app.route("/")
def helloWorld():
  return "Hello, cross-origin-world!"

Подробнее см. В документации Flask.

meagar
30 декабря 2014 в 06:12
204

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

ZurabWeb
26 февраля 2015 в 16:37
158

Несмотря на то, что это могло быть небезопасно, вопрос был не в безопасности, а в том, как выполнить задачу. Это один из вариантов, который разработчик должен выбрать при работе с междоменными запросами AJAX. Это помогло мне решить проблему, и для моего приложения мне все равно, откуда пришли данные. Я дезинфицирую весь ввод с помощью PHP в целевом домене, поэтому, если кто-то хочет отправить на него какой-то мусор, пусть попробует. Главное здесь то, что междоменный AJAX может быть разрешен из целевого домена. +1 за ответ.

shruti
29 сентября 2021 в 15:05
2

@meagar Согласен с вами, что мы не должны выключать CORS, но иногда нам нужно тестировать приложение во время его разработки, и для этого самый простой способ - выключить CORS и проверить, все ли работает нормально. Часто фронтенд-разработчики не имеют доступа к бэкэнд-системе, где они могут что-то изменить, или им нужно написать для этого прокси. Лучший способ добавить расширение chrome, которое отключает CORS для целей разработки, как написано в удаленном ответе.