Відповідь на запит перед польотом не проходить перевірку контролю доступу


456

Я отримую цю помилку за допомогою ngResource для виклику API REST у веб-службах Amazon:

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 на стороні сервера.
Отримати

4
У будь-якому випадку ваші голоси, які виголосили, неправильні. Він розміщує свої файли на своїй локальній машині. Не має значення, яку конфліктну ситуацію він робить на задньому боці. Кутовий не дозволить цього попереднього польоту.
Е. Маггіні

3
Що стосується коментарів, це спрацювало, коли я переключив браузер на захист
Андре Мендес

1
@Andre Але вимкнення безпеки - це лише потворне вирішення проблеми, коли ви
йдете

Відповіді:


240

Ви стикаєтеся з проблемами CORS.

Існує кілька способів виправити це.

  1. Вимкніть CORS. Наприклад: як вимкнути корзи в хромі
  2. Використовуйте плагін для свого браузера
  3. Використовуйте проксі, наприклад nginx. приклад налаштування
  4. Пройдіть необхідну установку для свого сервера. Це більше фактор веб-сервера, який ви завантажили у свій екземпляр EC2 (припускаючи, що це ви маєте на увазі під веб-службою Amazon). Для вашого конкретного сервера ви можете звернутися до веб-сайту увімкнення CORS.

Більш докладно, ви намагаєтеся отримати доступ до api.serverurl.com з localhost. Це точне визначення міждоменного запиту.

Якщо вимкнути його просто для того, щоб виконати свою роботу (гаразд, покладіть на вас низьку безпеку, якщо ви відвідуєте інші сайти і просто б'єте балон по дорозі), ви можете використовувати проксі-сервер, який змушує ваш браузер думати, що всі запити надходять від місцевого господаря, коли дійсно у вас локальний сервер, який потім викликає віддалений сервер.

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


Зараз за популярним попитом, на 100% більше інформації про CORS .... такий же чудовий смак!


А для нижніх людей .... обхід CORS - це саме те, що показано для тих, хто просто вивчає передню частину. https://codecraft.tv/courses/angular/http/http-with-promises/


774
вийшов із очевидного правильного впровадження CORS правильно
charlietfl

40
Голосувати нескладно. Менш легко ризикнути, мій друг. І все це працює саме в середовищі розробників.
Е. Маггіні

3
Це фактично спрацювало. Я додав прапор, щоб відключити захист Інтернету. Бо розвиток чудово.
Андре Мендес

15
@charlietfl Як?
GreenAsJade

3
Дякую, що ти врятував мені день. Використовується лише перший варіант: C: \ Program Files (x86) \ Google \ Chrome \ Application> chrome.exe --user-data-dir = "C: \ Chrome dev session" - відключення-веб-безпека. Від: 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 та whatthefish ставлять перед будь-яким виходом
Гарет Клаборн

Мій додаток клієнта перестав працювати, коли я додав заголовок, який вимагають лише деякі сервери. Якщо запит включає будь-які власні заголовки, їх потрібно буде вказати в Access-Control-Allow-Headers.
z0r

46

У веб-api 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 є там чомусь.
paqogomez

2
Просто для того, щоб зрозуміти @paqogomez у вашому методі ConfigureServices: services.AddCors (options => {options.AddPolicy ("AllowSpecificOrigin", builder => {builder.WithOrigins (" localhost" ) .AllowAnyOrigin () .AllowAnyHeader). AllowAnyMethod ();});}); та у вашому методі Налаштування: 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

Важливий заголовок максимального віку, в моєму випадку він не працюватиме без нього, я думаю, що браузеру потрібна інформація про те, наскільки тривалі "права доступу".

Крім того, якщо ви робите, наприклад, 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 за цим посиланням , і ви також повинні ознайомитись із цією публікацією SO


1
Ось стаття Mozilla, яка розповідає про те, як не можна використовувати підстановку для походження корсів: Посилання Очевидно, це стосується лише під час використання облікових даних (якщо я правильно розумію)
Helzgate,

Я використовую підстановку та надсилаю маркер носія для авторизації запиту, і він працює чудово, тому не впевнений, що посилання, яке я надав вище, стосується облікових даних. Моя проблема полягала в тому, що при складанні моєї політики CORS у .Net Core я не додав .AllowCredentials(). Після додавання .AllowCredentials()все працювало.
Гельцгейт

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?
Shubham Arya

@ShubhamArya на linux Debian за замовчуванням розміщено:/etc/apache2/apache2.conf
Tadej

де його можна знайти у вікнах?
Shubham Arya

10

Якщо ви пишете хромоване розширення

Ви повинні додати 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
це працює лише в експрес-програмах 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 - це не дуже вдалий спосіб , тому що якщо ви використовуєте його в іонному, звичайно, у мобільній збірці випуск знову виникне.

Тож краще виправити свій бекенд.

Перш за все У заголовку потрібно встановити-

  • заголовок ('Access-Control-Allow-Origin: *');
  • заголовок ('Набір заголовків Access-Control-Allow-Headers: "Походження, X-запитуваний-З, Тип вмісту, Прийняти"');

І якщо 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'])) заголовок ("Access-Control-Allow-Headers:
{$ _SERVER ['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}"); вихід (0); }


3

Дуже поширеною причиною цієї помилки може бути те, що хост-API присвоїв запит методу http (наприклад, PUT) і клієнт API викликає API за допомогою іншого методу http (наприклад, POST або GET)


Я правильно впроваджував CORS на своєму сервері, але забув додати PUTметод
fguillen

3

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

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

Ми не дуже впевнені, чому. Лол. Якщо хтось, дайте мені знати!
w00ngy

1

Я стикався з цією проблемою, коли для сервера DNS було встановлено 8.8.8.8 (google's). Власне, проблема була в маршрутизаторі, моя програма намагалася з'єднатися з сервером через google, а не локально (для мого конкретного випадку). Я видалив 8.8.8.8, і це вирішило проблему. Я знаю, що ці проблеми вирішуються за допомогою налаштувань CORS, але, можливо, хтось матиме ті ж проблеми, що і я


1

Я використовую AWS sdk для завантаження, витративши деякий час на пошук в Інтернеті, я натрапив на цю нитку. завдяки @lsimoneau 45581857 виявляється, саме те саме відбувалося. Я просто вказав свій запит на URL на мій відро, додавши варіант region, і він спрацював.

 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>від веб-сайтів / 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), прокручуючи. потім скопіюйте та вставте повне оголошення в ур-проект та запустіть його ... це буде працювати точно ... скопіюйте код коментаря та вставте в ur app.js або будь-який інший спроектуйте і спробуйте .. це буде працювати. це розблокує кожен спільний ресурс спільного використання. Тому ми можемо перемикатися між послугами для вашого використання

1
var express = вимагати ('express') var cors = вимагати ('cors') var app = express () app.use (cors ()) app.get ('/ products /: id', function (req, res, далі) {res.json ({msg: 'Це увімкнено CORS для всіх джерел!'})}) app.listen (80, function () {console.log ('Прослуховування веб-сервера з підтримкою CORS на порт 80' )})
Рахул sah

-1

Щось дуже легко пропустити ...

Провідник рішень IN, клацніть правою кнопкою миші api-проект. У вікні властивостей встановіть "Анонімну автентифікацію" на Увімкнено !!!


-8

Вимкніть безпеку хрому. Створіть ярлик у 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.