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

javascript jquery cors same-origin-policy flask-restless


Примечание для мода : Этот вопрос о том, почему Postman не подчиняется ограничениям CORS так же, как XMLHttpRequest. Этот вопрос не о том, как исправить ошибку "Нет 'Access-Control-Allow-Origin' ...".

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

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

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

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




Answer 1 MD. Sahib Bin Mahboob


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

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

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




Answer 2 Shady Sherif


ПРЕДУПРЕЖДЕНИЕ. Использование 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

Затем включите флэш-корса в ваше приложение.

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 .




Answer 3 George Livingston


Because
$ .ajax ({type: "POST" - вызывает OPTIONS
$ .post ( - вызывает POST

Оба они разные.Почтальон правильно называет "POST",но когда мы его называем,то это будут "ВНИМАНИЯ".

Для веб-сервисов C # - веб-API

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

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

Пожалуйста,убедитесь,что вы не совершаете ошибку в звонке по "Аяксу".

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

Выпуск Angular 4 - пожалуйста, обратитесь к http://www.hubfly.com/blog/solutions/how-to-fix-angular-4-api-call-issues/

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

System.Net.WebClient wc = new System.Net.WebClient();
string str = wc.DownloadString("http://mysite.microsoft.sample.xyz.com/api/mycall");



Answer 4 Gopinath


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

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

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

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




Answer 5 Kamil Kiełczewski


В приведенном ниже исследовании в качестве 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

Это стандартный способ отправки запросов почтальоном. Но браузер отправляет запросы по-разному, когда ваш сайт и 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"