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

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


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

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

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

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

$.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);
    });
2801
Mr Jedi 17 Ноя 2013 в 23:29

11 ответов

Лучший ответ

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

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

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

1476
Prabhat 1 Мар 2021 в 09:22

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

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

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

Если вы используете красный узел, вы должны разрешить 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.

296
Machavity 27 Янв 2020 в 03:06

Потому что
$. ajax ({тип: "POST" - вызывает ОПЦИИ
$. post ( - звонки POST

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

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

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

<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");
82
Community 20 Июн 2020 в 09:12

Если вы хотите обойти это ограничение при получении содержимого с помощью fetch API или XMLHttpRequest в javascript, вы можете использовать прокси-сервер, чтобы он установил заголовок Access-Control-Allow-Origin на *.

const express = require('express');
const request = require('request');

const app = express();

app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*');
  next();
});

app.get('/fetch', (req, res) => {
  request(
    { url: req.query.url },
    (error, response, body) => {
      if (error || response.statusCode !== 200) {
        return res.status(500).send('error');
      }
      res.send(body);
    }
  )
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`listening on ${PORT}`));

Выше приведен пример кода (требуется узел Js), который может действовать как прокси-сервер. Например: если я хочу получить https://www.google.com, обычно выдается ошибка CORS, но теперь, поскольку запрос отправляется через прокси-сервер, размещенный локально на порту 3000, прокси-сервер добавляет заголовок Access-Control-Allow-Origin в ответ, и не будет никаких проблем.

Отправьте запрос GET на http: // localhost: 3000 / fetch? Url = Your URL here вместо того, чтобы напрямую отправлять запрос на URl, который вы хотите получить.

Your URL here обозначает URL-адрес, который вы хотите получить, например: https://www.google.com

13
Adwaith 21 Июл 2020 в 17:06

Только для проекта .NET Core Web API добавьте следующие изменения:

  1. Добавьте следующий код после строки services.AddMvc() в методе ConfigureServices() файла Startup.cs:
services.AddCors(allowsites=>{allowsites.AddPolicy("AllowOrigin", options => options.AllowAnyOrigin());
            });
  1. Добавьте следующий код после строки app.UseMvc() в метод Configure() файла Startup.cs:
app.UseCors(options => options.AllowAnyOrigin());
  1. Откройте контроллер, к которому вы хотите получить доступ за пределами домена, и добавьте следующий атрибут на уровне контроллера:
[EnableCors("AllowOrigin")]
4
David Buck 18 Апр 2020 в 17:24

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

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

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

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

7
JacquesB 6 Апр 2021 в 10:15

Вы используете веб-шрифты от Google, Typekit и т. Д.? Существует несколько способов использования веб-шрифтов, таких как методы @ font-face или CSS3. Некоторые браузеры, такие как Firefox и IE, могут отказываться встраивать шрифт, если он поступает с нестандартного стороннего URL (например, вашего блога) по той же причине безопасности.

Чтобы исправить проблему в вашем блоге WordPress, просто поместите ниже в свой файл .htaccess.

<IfModule mod_headers.c>
  <FilesMatch "\.(ttf|ttc|otf|eot|woff|woff2|font.css|css|js)$">
  Header set Access-Control-Allow-Origin "*"
  </FilesMatch>
</IfModule>

Источник: https://crunchify.com/how-to-fix-access-control-allow-origin-issue-for-your-https-enabled-wordpress-site-and-maxcdn/

-1
Mizhar Raja 6 Дек 2020 в 01:02

Если вы используете .NET в качестве среднего уровня, четко проверьте атрибут маршрута, например,

У меня была проблема, когда это было так,

[Route("something/{somethingLong: long}")] //Space.

Исправлено этим,

[Route("something/{somethingLong:long}")] //No space
-1
Sai Vaibhav Medavarapu 9 Мар 2020 в 17:08

Обнаружена одна и та же ошибка в другом варианте использования.

Пример использования: в Chrome при попытке вызвать конечную точку Spring REST в angular.

enter image description here

Решение: добавьте аннотацию @CrossOrigin ("*") поверх соответствующего класса контроллеров.

enter image description here

14
Kms 25 Май 2020 в 05:45

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

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

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

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

21
Peter Mortensen 8 Мар 2020 в 18:09

В приведенном ниже исследовании в качестве 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"
30
Peter Mortensen 26 Янв 2020 в 19:09