Ответ на предполетный запрос не проходит проверку контроля доступа


458

Я получаю эту ошибку, используя ngResource для вызова REST API в Amazon Web Services:

XMLHttpRequest не может загрузить http://server.apiurl.com:8000/s/login?login=facebook . Ответ на запрос предварительной проверки не проходит проверку контроля доступа: в запрошенном ресурсе отсутствует заголовок «Access-Control-Allow-Origin». Поэтому происхождение ' http: // localhost ' не разрешено. Ошибка 405

Обслуживание:

socialMarkt.factory('loginService', ['$resource', function($resource){    
    var apiAddress = "http://server.apiurl.com:8000/s/login/";
    return $resource(apiAddress, { login:"facebook", access_token: "@access_token" ,facebook_id: "@facebook_id" }, {
                getUser: {method:'POST'}
            });
}]);

контроллер:

[...]
loginService.getUser(JSON.stringify(fbObj)),
                function(data){
                    console.log(data);
                },
                function(result) {
                    console.error('Error', result.status);
                }
[...]

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


растерян: вы «настраивали сервер» или это «API отдыха на веб-сервисе Amazon»?
dandavis

3
Вы явно не сделали достаточно, чтобы включить CORS на стороне сервера. Опубликовать образец заголовков ответа
charlietfl

4
В любом случае ваши отрицательные голоса неверны. Он размещает свои файлы на своем локальном компьютере. Не имеет значения, какой конф он делает на заднем плане. Угловой не позволит этот предварительный полет.
Э. Маггини

3
Спасибо за комментарии, это сработало, когда я настроил браузер на безопасность
Андре Мендес,

1
@ Андре. Но отключение безопасности - это просто уродливый обходной путь, когда вы
Шиви

Ответы:


241

Вы сталкиваетесь с проблемами CORS.

Есть несколько способов исправить / обойти это.

  1. Выключите CORS. Например: как отключить cors в chrome
  2. Используйте плагин для вашего браузера
  3. Используйте прокси, такой как nginx. пример того, как настроить
  4. Пройдите необходимые настройки для вашего сервера. Это в большей степени зависит от того, какой веб-сервер вы загрузили в своем экземпляре EC2 (предположим, что именно это вы подразумеваете под «веб-сервисом Amazon»). Для вашего конкретного сервера вы можете обратиться к веб-сайту включения CORS.

Более подробно, вы пытаетесь получить доступ к api.serverurl.com с локального хоста. Это точное определение междоменного запроса.

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

поэтому api.serverurl.com может стать localhost: 8000 / api, и ваш локальный nginx или другой прокси-сервер отправит в правильный пункт назначения.


Теперь по многочисленным просьбам, на 100% больше информации о CORS .... такой же прекрасный вкус!


И для downvoters .... в обход CORS это именно то, что показано для тех, кто просто изучает интерфейс. https://codecraft.tv/courses/angular/http/http-with-promises/



40
Легко понизить голосование. Менее легко рисковать собой, друг мой. И все это работает именно в среде разработчика.
Э. Маггини

3
Это действительно сработало. Я добавил флаг, чтобы отключить веб-безопасность. Для развития это хорошо.
Андре Мендес

15
@charlietfl Как?
GreenAsJade

3
Спасибо, что ты спас мой день. Использовать только первый вариант: C: \ Program Files (x86) \ Google \ Chrome \ Application> chrome.exe --user-data-dir = "C: \ Chrome dev session" --disable-web-security. От: stackoverflow.com/questions/3102819/…
Harsimer

169

Мой «API-сервер» является приложением PHP, поэтому для решения этой проблемы я нашел следующее решение:

Поместите строки в index.php

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token');

3
Я согласен, это лучше, чем принятый ответ, хотя будьте осторожны при копировании этих строк, обязательно измените методы и происхождение.
Амир Саванд

11
Где поместить это в проект Angular 6?
Whatthefish

@CodyBugstein и то, что ставят перед выходом
Гарет Клаборн

Мое клиентское приложение перестало работать, когда я добавил заголовок, который требуется только для некоторых серверов. Если запрос включает какие-либо пользовательские заголовки, они должны быть перечислены в Access-Control-Allow-Headers.
z0r

47

В веб-интерфейсе AspNetCore эта проблема была исправлена ​​путем добавления «Microsoft.AspNetCore.Cors» (версия 1.1.1) и добавления указанных ниже изменений в файл Startup.cs.

public void ConfigureServices(IServiceCollection services)
{ 
    services.AddCors(options =>
    {
          options.AddPolicy("AllowAllHeaders",
                builder =>
            {
                    builder.AllowAnyOrigin()
                           .AllowAnyHeader()
                           .AllowAnyMethod();
                });
    });
    .
    .
    .
}

а также

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{


    // Shows UseCors with named policy.
    app.UseCors("AllowAllHeaders");
    .
    .
    .
}

и надевая [EnableCors("AllowAllHeaders")]контроллер.


18
Это хороший ответ, если вы хотите встроить уязвимости межсайтового скриптинга! Пожалуйста, никогда не делайте этого! Укажите свои домены, к которым вы можете получить доступ, чтобы избежать проблем с безопасностью. CORS существует по причине.
Пакогомес

2
Просто чтобы прояснить это, @paqogomez, в вашем методе ConfigureServices: services.AddCors (options => {options.AddPolicy ("AllowSpecificOrigin", builder => {builder.WithOrigins (" localhost" ) .AllowAnyOrigin () .AllowAnyHeader (). AllowAnyMethod ();});}); и в вашем методе Configure: app.UseCors ("AllowSpecificOrigin");
Франциско Тена

28

Есть некоторые оговорки, когда речь идет о CORS. Во-первых, он не допускает подстановочные знаки, *но не держите меня на этом, я где-то читал, и я не могу найти статью сейчас.

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

 Access-Control-Allow-Origin: www.other.com 

Если вы делаете запросы , которые влияют на ресурсы сервера , как POST / PUT / PATCH, и если мим тип отличается от следующего application/x-www-form-urlencoded, multipart/form-dataили text/plainбраузер автоматически сделает предполетной OPTIONS запроса проверки с сервером , если это позволит его ,

Таким образом, ваш API / сервер должен обрабатывать эти запросы OPTIONS соответственно, вы должны ответить соответствующим образом, access control headersи код статуса ответа http должен быть 200.

Заголовки должны быть примерно такими, настройте их под свои нужды:

   Access-Control-Allow-Methods: GET, POST, PUT, PATCH, POST, DELETE, OPTIONS
   Access-Control-Allow-Headers: Content-Type
   Access-Control-Max-Age: 86400

Заголовок max-age важен, в моем случае он не будет работать без него, я думаю, браузеру нужна информация о том, как долго действительны «права доступа».

Кроме того, если вы делаете, например, POSTзапрос с application/jsonmime из другого домена, вам также необходимо добавить ранее упомянутый заголовок разрешения источника, так что это будет выглядеть так:

   Access-Control-Allow-Origin: www.other.com 
   Access-Control-Allow-Methods: GET, POST, PUT, PATCH, POST, DELETE, OPTIONS
   Access-Control-Allow-Headers: Content-Type
   Access-Control-Max-Age: 86400

Когда пре-полет пройдет успешно и получит всю необходимую информацию, ваш фактический запрос будет выполнен.

Вообще говоря, все Access-Controlзаголовки, которые запрашиваются в первоначальном или предполетном запросе, должны быть указаны в ответе, чтобы он работал.

Вот хороший пример в документации по MDN по этой ссылке , и вы также должны проверить этот пост


1
Вот статья в Mozilla, рассказывающая о том, как нельзя использовать подстановочный знак для происхождения коров: Ссылка Итак, очевидно, это применимо только при использовании учетных данных (если я правильно понимаю)
Helzgate

Я использую подстановочный знак и отправляю токен на предъявителя, чтобы авторизовать запрос, и он работает нормально, поэтому не уверен, на что ссылается приведенная выше ссылка в отношении учетных данных. Моя проблема заключалась в том, что при разработке моей политики CORS в .Net Core я не добавил .AllowCredentials(). После добавления .AllowCredentials()все заработало.
Helzgate

15

JavaScript XMLHttpRequest и Fetch следуют одной и той же политике происхождения. Таким образом, веб-приложение, использующее XMLHttpRequest или Fetch, может только отправлять HTTP-запросы к своему собственному домену.

Источник: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

Вы должны отправить Access-Control-Allow-Origin: * HTTP-заголовок со стороны вашего сервера.

Если вы используете Apache в качестве HTTP-сервера, вы можете добавить его в файл конфигурации Apache следующим образом:

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

Mod_headers по умолчанию включен в Apache, однако вы можете убедиться, что он включен, запустив:

 a2enmod headers

Где я могу найти свой конфигурационный файл Apache?
Шубхам Арья

@ShubhamArya в linux Debian, расположение по умолчанию:/etc/apache2/apache2.conf
Tadej

где я могу найти его в windows?
Шубхам Арья

10

Если вы пишете Chrome-расширение

Вы должны добавить в manifest.jsonразрешения для вашего домена (ов).

"permissions": [
   "http://example.com/*",
   "https://example.com/*"
]

1
Также проверьте, есть ли у вас префикс www
Влас Башинский

8

Если вы используете сервер IIS случайно. Вы можете установить заголовки ниже в опции заголовков HTTP-запроса.

Access-Control-Allow-Origin:*
Access-Control-Allow-Methods: 'HEAD, GET, POST, PUT, PATCH, DELETE'
Access-Control-Allow-Headers: 'Origin, Content-Type, X-Auth-Token';

с этим все сообщения, получить и т. д., будет работать нормально.



5

В PHP вы можете добавить заголовки:

<?php
header ("Access-Control-Allow-Origin: *");
header ("Access-Control-Expose-Headers: Content-Length, X-JSON");
header ("Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS");
header ("Access-Control-Allow-Headers: *");
...

спасибо, у меня это сработало! в тестах и ​​производственной среде. Даже используя https: //
Jose Seie

1
@atiruz Спасибо за решение. Это работает, когда я добавил строкуheader ("Access-Control-Expose-Headers: Content-Length, X-JSON");
Silambarasan RD

5

Чтобы устранить проблемы перекрестных исходных запросов в приложении Node JS:

npm i cors

И просто добавьте строки ниже к app.js

let cors = require('cors')
app.use(cors())

3
это работает только в приложениях Express JS, но не во всех приложениях для узлов
DrCord

3

В моем конфигурационном файле Apache VirtualHost я добавил следующие строки:

Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header always set Access-Control-Max-Age "1000"
Header always set Access-Control-Allow-Headers "x-requested-with, Content-Type, origin, authorization, accept, client-security-token"

RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]

3

Для тех, кто использует Lambda Integrated Proxy с API-шлюзом . Вам необходимо настроить лямбда-функцию так, как если бы вы отправляли ей запросы напрямую, то есть функция должна правильно настраивать заголовки ответа. (Если вы используете пользовательские лямбда-функции, это будет обрабатываться шлюзом API.)

//In your lambda's index.handler():
exports.handler = (event, context, callback) => {
     //on success:
     callback(null, {
           statusCode: 200,
           headers: {
                "Access-Control-Allow-Origin" : "*"
           }
     }
}

1
Я также хочу присоединиться и упомянуть одну большую ошибку, я не думаю, что документы AWS. Скажем, вы используете API-шлюз для прокси-функции вашей лямбда-функции, и вы используете какой-то API в этой лямбда-функции. Если этот API возвращает код успеха не-200 и вы не добавили код успеха не-200 в ответ метода в шлюзе API, вы получите сообщение об ошибке и не увидите свой успешный ответ . Примеры для этого: Sendgrid и Twilio имеют не 200 кодов успеха.
Стивен Тетро

3

Я думаю, что отключение CORS из Chrome не очень хороший способ , потому что, если вы используете его в ионном режиме, то, безусловно, в Mobile Build проблема снова возникнет.

Так что лучше исправить в своем бэкэнде.

Прежде всего, в заголовке нужно установить

  • заголовок ('Access-Control-Allow-Origin: *');
  • header ('Заголовки set Access-Control-Allow-Headers: "Origin, X-Requested-With, Content-Type, Accept"');

И если API ведет себя как GET и POST, то и в вашем заголовке

if ($ _SERVER ['REQUEST_METHOD'] == 'OPTIONS') {if (isset ($ _ SERVER ['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))) заголовок ("Методы контроля доступа: GET, POST, OPTIONS");
заголовок if (isset ($ _ SERVER ['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) ("Заголовки контроля доступа:
{$ _SERVER ['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}"); Выход (0); }


3

Чаще всего причиной этой ошибки может быть то, что API хоста сопоставил запрос с методом http (например, PUT), а клиент API вызывает API, используя другой метод http (например, POST или GET).


Я правильно PUT
внедрял

3

Наша команда иногда видит это, используя Vue, axios и C # WebApi. Добавление атрибута маршрута в конечную точку, к которой вы пытаетесь попасть, исправляет его для нас.

[Route("ControllerName/Endpoint")]
[HttpOptions, HttpPost]
public IHttpActionResult Endpoint() { }

Мы не совсем уверены, почему. Лол. Если кто-нибудь, дайте мне знать!
w00ngy

1

Я столкнулся с этой проблемой, когда DNS-сервер был установлен на 8.8.8.8 (Google's). На самом деле проблема была в роутере, мое приложение пыталось соединиться с сервером через гугл, а не локально (для моего конкретного случая). Я удалил 8.8.8.8, и это решило проблему. Я знаю, что эти проблемы решаются настройками CORS, но, возможно, у кого-то будут такие же проблемы, как у меня


1

Я использую AWS SDK для загрузки, потратив некоторое время на поиск в Интернете, я наткнулся на эту тему. благодаря @lsimoneau 45581857 выясняется, что происходит то же самое. Я просто направил свой URL-адрес запроса на регион, добавив параметр региона, и это сработало.

 const s3 = new AWS.S3({
 accessKeyId: config.awsAccessKeyID,
 secretAccessKey: config.awsSecretAccessKey,
 region: 'eu-west-2'  // add region here });

0

Автономные дистрибутивы GeoServer включают сервер приложений Jetty. Включите общий доступ к ресурсам между источниками (CORS), чтобы приложения JavaScript за пределами вашего собственного домена могли использовать GeoServer.

Раскомментируйте следующее <filter>и <filter-mapping>от webapps / geoserver / WEB-INF / web.xml:

<web-app>
  <filter>
      <filter-name>cross-origin</filter-name>
      <filter-class>org.eclipse.jetty.servlets.CrossOriginFilter</filter-class>
  </filter>
  <filter-mapping>
      <filter-name>cross-origin</filter-name>
      <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

Это не добавляло ничего в заголовок ответа, поэтому оно не работало
JollyRoger,

1
не использовал GeoServer, но этот клип помог мне узнать настройки, которые я должен использовать в приложении, получающем вызов.
Мэтт Фелзани

0

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

  1. открыть ( https://www.npmjs.com/package/cors#enabling-cors-pre-flight )
  2. перейдите к установке и скопируйте команду npm install cors для установки через терминал узла
  3. перейдите в раздел «Простое использование (включить все запросы CORS)» с помощью scrolling.then, скопируйте и вставьте полное объявление в проект ur и запустите его ... это будет работать наверняка .. скопируйте код комментария и вставьте его в ur app.js или любой другой спроектировать и попробовать ... это сработает. это откроет все ресурсы общего доступа к источникам .. поэтому мы можем переключаться между подачами для вашего использования

1
var express = require ('express') var cors = require ('cors') var app = express () app.use (cors ()) app.get ('/ products /: id', функция (req, res, next) {res.json ({msg: 'Это с поддержкой CORS для всех источников!'})}) app.listen (80, function () {console.log ('Веб-сервер с поддержкой CORS, прослушивающий порт 80') )})
Рахул

-1

То, что очень легко пропустить ...

В обозревателе решений щелкните правой кнопкой мыши api-проект. В окне свойств установите «Анонимная аутентификация» на Включено !!!


-8

Отключите безопасность Chrome. Создайте ярлык Chrome правой кнопкой мыши -> Свойства -> Цель, вставьте этот «C: \ Program Files (x86) \ Google \ Chrome \ Application \ chrome.exe» --disable-web-security --user -data-DIR = "C: / chromedev"

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.