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

299

Я получаю эту ошибку, используя ngResource, чтобы вызвать REST API для веб-служб 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.

  • 0
    растерян: вы «настраивали сервер» или это «API отдыха на веб-сервисе Amazon»?
  • 3
    Вы явно не сделали достаточно, чтобы включить CORS на стороне сервера. Опубликовать образец заголовка ответа
Показать ещё 6 комментариев
Теги:
http
cors
http-status-code-405

20 ответов

163
Лучший ответ

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

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

  1. Выключите CORS. Например: как отключить cors в chrome
  2. Используйте плагин для вашего браузера
  3. Используйте прокси, такой как nginx. пример того, как настроить

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

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

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


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


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

  • 554
    упустил очевидную правильную реализацию CORS
  • 26
    Легко понизить голосование. Менее легко рисковать собой, друг мой. И все это работает именно в среде разработчика.
Показать ещё 9 комментариев
131

Мой "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');
  • 2
    Я согласен, это лучше, чем принятый ответ, хотя будьте осторожны при копировании этих строк, обязательно измените методы и происхождение.
  • 0
    Куда ты это положил? В корне получить конечную точку?
Показать ещё 2 комментария
34

В AspNetCore web api эта проблема исправлена ​​добавлением "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")] на контроллер.

  • 14
    Это хороший ответ, если вы хотите встроить уязвимости межсайтового скриптинга! Пожалуйста, никогда не делайте этого! Укажите свои домены, к которым вы можете получить доступ, чтобы избежать проблем с безопасностью. CORS существует по причине.
  • 1
    Просто чтобы сделать это более понятным @paqogomez, в вашем методе ConfigureServices: services.AddCors (options => {options.AddPolicy ("AllowSpecificOrigin", builder => {builder.WithOrigins (" localhost" ) .AllowAnyOrigin () .AllowAnyHeader (). AllowAnyMethod ();});}); и в вашем методе Configure: app.UseCors ("AllowSpecificOrigin");
14

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

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

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

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

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

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

 a2enmod headers
  • 0
    Где я могу найти свой конфигурационный файл Apache?
  • 0
    @ShubhamArya в Linux Debian, расположение по умолчанию: /etc/apache2/apache2.conf
Показать ещё 1 комментарий
7

Если вы пишете хром-расширение

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

"permissions": [
   "http://example.com/*",
   "https://example.com/*"
]
  • 1
    Также проверьте, если у вас есть префикс www
  • 1
    спас мой бекон!
5

Если вы случайно используете сервер 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';

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

4

Для сервера флагов python вы можете использовать плагин-флагов, чтобы разрешать запросы на междоменные запросы.

Смотрите: https://flask-cors.readthedocs.io/en/latest/

3

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

Если вы делаете запросы из другого домена, вам нужно добавить разрешенные заголовки источника. Access-Control-Allow-Origin: www.other.com

Если вы делаете запросы, которые влияют на ресурсы сервера, такие как POST/PUT/PATCH, и если тип mime отличается от следующего 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/json mime из другого домена, вам также необходимо добавить ранее упомянутый заголовок источника разрешения, поэтому он будет выглядеть так:

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

  • 0
    Хороший ответ! Интересно, никаких голосов за это.
3

В 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: *");
...
  • 0
    Схематично, но работает в тестовой среде
  • 2
    Спасибо! это сэкономило мне время
Показать ещё 2 комментария
2

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

//In your lambda 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 успешных кодов.
2

В моем конфигурационном файле 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]
1

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

[Route("ControllerName/Endpoint")]
[HttpOptions, HttpPost]
public IHttpActionResult Endpoint() { }
  • 0
    Мы не совсем уверены, почему. Лол. Если кто-нибудь, дайте мне знать!
1

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

npm i cors

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

let cors = require('cors')
app.use(cors())
  • 0
    Работает отлично! Это отличный ответ
1

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

  • 0
    Я правильно внедрял CORS на своем сервере, но я забыл добавить метод PUT
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 });
1

Отдельные дистрибутивы 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>
  • 0
    Это не добавило антихинга в заголовок ответа, поэтому не сработало
  • 1
    не использовал GeoServer, но этот клип помог мне узнать настройки, которые я должен использовать в приложении, получающем вызов.
1

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

0

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

Так лучше исправить в вашем Backend.

Прежде всего в заголовке заголовка, вам нужно set-

  • header ('Access-Control-Allow-Origin: *');
  • header ('Header set Access-Control-Allow-Headers: "Origin, X-Requested-With, Content-Type, Accept"');

И если API ведет себя как GET и POST, то и Set в вашем header-

if ($ _SERVER ['REQUEST_METHOD'] == 'OPTIONS') {if (isset ($ _ SERVER ['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])) заголовок ("Access-Control-Allow-Methods: GET, POST, OPTIONS");
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) header("Access-Control-Allow-Headers: if (isset ($ _ SERVER ['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) заголовок ("Access-Control-Allow-Headers:
{$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}"); exit(0); } {$ _SERVER ['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'}} "); exit (0);}

0

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

В проводнике решений, щелкните правой кнопкой мыши api-project. В окне свойств установите "Анонимная аутентификация" на "Включено".

-6

Отключите chrome security.Create chrome shortcut right click → properties → target, вставьте это "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --disable-web-security --user -data-DIR = "C: /chromedev"

Ещё вопросы

Сообщество Overcoder
Наверх
Меню