Почему мой JavaScript получает сообщение об ошибке «Отсутствует заголовок« Access-Control-Allow-Origin »на запрошенном ресурсе», а Postman - нет?

2045

Я пытаюсь сделать авторизацию с помощью 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);
    });
  • 24
    Вы делаете запрос от localhost или прямо выполняете HTML?
  • 0
    @ MD.SahibBinMahboob Если я понимаю ваш вопрос, я запрашиваю у localhost - у меня есть страница на моем компьютере, и я просто запускаю ее. Когда я размещаю сайт на хостинге, он дает тот же результат.
Показать ещё 9 комментариев
Теги:
cors
restful-authentication
same-origin-policy
flask-restless

40 ответов

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

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

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

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

  • 5
    Ты прав. Я делаю запрос на другой домен, чем моя страница. API находится на сервере, и я запускаю запрос от localhost. Прежде чем я приму ответ, вы можете объяснить, что означает «выполнение запроса напрямую»? POSTMAN не используете домен?
  • 151
    Браузер не блокирует запрос. Единственные браузеры, которые напрямую блокируют запросы кросс-исходных ajax, - это IE7 или старше. Все браузеры, кроме IE7 и более старых, реализуют спецификацию CORS (IE8 и IE9 частично). Все, что вам нужно сделать, это подписаться на запросы CORS на вашем сервере API, возвращая соответствующие заголовки на основе запроса. Вы должны прочитать о концепциях CORS на mzl.la/VOFrSz . Почтальон также отправляет запросы через XHR. Если вы не видите ту же проблему при использовании почтальона, это означает, что вы неосознанно не отправляете тот же запрос через почтальона.
Показать ещё 12 комментариев
478

Это не исправление для производства или когда приложение должно быть показано клиенту, это полезно только тогда, когда пользовательский интерфейс и бэкэнд разработка находятся на разных серверах и в они фактически находятся на одном сервере. Например: при разработке пользовательского интерфейса для любого приложения, если есть необходимость протестировать его локально, указывая на сервер бэкэнд, в этом случае это идеальное решение. Для производственного исправления заголовки CORS должны быть добавлены на серверный сервер, чтобы разрешить доступ к перекрестному контенту.

Самый простой способ - просто добавить расширение в google chrome, чтобы разрешить доступ с помощью CORS.

(https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi?hl=en-US)

Просто включите это расширение, если вы хотите разрешить доступ к запросу заголовка 'access-control-allow-origin'.

Или

В Windows вставьте эту команду в окно выполнить

chrome.exe --user-data-dir="C:/Chrome dev session" --disable-web-security

это откроет новый браузер chrome, который разрешит доступ к запросу заголовка "access-control-allow-origin-origin" .

  • 0
    Я пытаюсь использовать этот инструмент CORS, но я не знаю, как его использовать. Вы можете помочь мне с этим?
  • 0
    @Ruby_Pry просто добавьте расширение из приведенного выше URL-адреса, и затем вы увидите значок приложения CORS в верхней левой части браузера Chrome, нажмите на него, вы увидите всплывающее окно, где вы можете включить его всякий раз, когда вы хотите разрешить доступ через CORS.
Показать ещё 17 комментариев
306

Если вы вернетесь в JSON, попробуйте использовать JSONP (обратите внимание на P в конце) для разговора между доменами:

$.ajax({
  type: "POST",
  dataType: 'jsonp',
  ...... etc ......

Подробнее о работе с JSONP здесь:

Появление JSONP - по существу согласованного межсайтового скриптинга - открыло дверь для мощных mashups контента. Многие известные сайты предоставляют услуги JSONP, позволяя вам получать доступ к их контенту через предопределенный API.

  • 2
    С NodeJs с типом данных json работал, с ASP.Net это было виновником
  • 84
    Имейте в виду, что jsonp не работает с содержимым POST. Больше обсуждений здесь .
Показать ещё 7 комментариев
190

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

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

Предупреждение. Это содержит проблему безопасности для вашего PHP файла, которую он может вызвать злоумышленники. вы должны использовать сеансы и файлы cookie для проверки подлинности, чтобы предотвратить ваш файл/службу от этой атаки. Ваш сервис уязвим для подделки подделок (CSRF).

Если вы используете 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"
},
  • 314
    Вопрос был совсем не о PHP.
  • 83
    и это не безопасно
Показать ещё 12 комментариев
156

Я хочу, чтобы кто-то поделился этим сайтом со мной давно http://cors.io/, он бы сэкономил массу времени по сравнению со строительством и полагался на мой собственный прокси. Однако, когда вы переходите к производству, ваш собственный прокси-сервер является лучшим выбором, поскольку вы все еще контролируете все аспекты своих данных.

Все, что вам нужно:

https://cors.io/?http://HTTP_YOUR_LINK_HERE

  • 28
    Каковы недостатки этого? Эти парни перехватывают мои данные?
  • 1
    ..Это приложение временно превысило свою квоту. Пожалуйста, попробуйте позже.
Показать ещё 15 комментариев
64

Если вы используете Node.js, попробуйте:

app.use(function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    next();
});

Дополнительная информация: CORS на ExpressJS

  • 5
    Я отдаю вам голос, потому что это именно то, что мне было нужно. Но считаю плохой идеей продвигать пример "*", не объясняя, что он допускает любое соединение и не должен использоваться в производстве. Это объясняется по ссылке MDN developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS .
  • 0
    @rob спасибо за ваш комментарий. Вы правы, мы должны указать, каким источникам разрешено использовать ресурсы. Но в случае, если ресурсы используются в общественных целях, и мы не знаем потребителей, я думаю, что мы должны пойти с "*", если я не ошибаюсь.
Показать ещё 3 комментария
60

Там есть проблема с несколькими доменами, использующая Ajax. Вы должны быть уверены, что получаете доступ к своим файлам на одном и том же пути http:// без www. (или доступа из http://www. и отправляете на тот же путь, включая www.), который браузер рассматривает как другой домен при доступе через www., поэтому вы видите, где проблема. Вы отправляете в другой домен, и браузер блокирует поток из-за проблемы с выпуском.

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

  • 0
    да, я был вынужден сделать это в моем приложении телефонной пробки, var app_url = location.protocol + '//' + location.host + '/ api /. проблема была с сайтом www. добавленный принесет эту ошибку.
50

Так как
$.ajax({типа: "POST" - вызовы OPTIONS
$.post( - вызывает POST

оба разных почтальона правильно называют "POST", но при вызове это будет "OPTIONS"

Для веб-сервисов С# - webapi

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

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

Выпуск 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");
  • 0
    Этот конфиг решил ту же ошибку на Wordpress в Azure Services. Благодарю.
  • 8
    Я бы предложил использовать конкретное значение источника, чтобы избежать запросов от внешних доменов. Так, например, вместо * используйте https://www.myotherdomain.com
23

Попробуйте XDomain,

Реферат: Чистая альтернатива JavaScript CORS/ polyfill. Не требуется настройка сервера - просто добавьте proxy.html в домене, с которым вы хотите общаться. Эта библиотека использует XHook для привязки всех XHR, поэтому XDomain должен работать совместно с любой библиотекой.

11

Если вы не хотите, чтобы:

  1. Отключить веб-безопасность в Chrome
  2. Используйте JSONP
  3. Используйте сторонний сайт для перенаправления ваших запросов

и вы уверены, что на вашем сервере включена поддержка CORS (протестируйте CORS здесь: http://www.test-cors.org/)

Затем вам нужно передать параметр origin с вашим запросом. Этот источник ДОЛЖЕН соответствовать источнику, который ваш браузер отправляет с вашим запросом.

Вы можете увидеть это в действии здесь: http://www.wikinomad.com/app/detail/Campgrounds/3591

Функция редактирования отправляет запрос GET & POST в другой домен для извлечения данных. Я установил параметр источника, который решает проблему. Бэкэнд - это движок mediaWiki.

TL;DR: добавьте параметр "origin" к вашим вызовам, который должен быть параметром Origin, который отправляет ваш браузер (вы не можете подделать параметр origin)

  • 1
    Вы ссылаетесь на этот пример кода из main.min.js ?: t.post("https://wiki.wikinomad.com/api.php?origin=https://www.wikinomad.com", n, o).then(function(e) {... Если это так, то не правда ли, что этот способ указания источника требует, чтобы PHP, обслуживаемый из "бэкэнда", был закодирован для его поддержки, и этот ответ не будет работать иначе?
  • 1
    @ CODE-REaD, да, это верно, что бэкэнд должен также поддерживать CORS.
8

Основываясь на ответе на shruti, я создал ярлык браузера Chrome с необходимыми аргументами: Изображение 2060 Изображение 2061

  • 70
    Отлично. Теперь мне нужно обойтись со своими 100 000 пользователей и отключить их веб-безопасность на Chrome.
  • 7
    @GaneshKrishnan Спрашивающий, кажется, разработчик, и его вопрос (по моему мнению), кажется, для целей развития, как и моя проблема. И да, если вы хотите взломать своих пользователей, обойдите их и отключите их веб-безопасность в Chrome :)
8

У меня была следующая конфигурация, приводящая к той же ошибке при запросе ответов с сервера.

Серверная сторона: SparkJava → предоставляет REST-API
Клиентская сторона: ExtJs6 → обеспечивает рендеринг браузера

На стороне сервера мне пришлось добавить это в ответ:

Spark.get("/someRestCallToSpark", (req, res) -> {
    res.header("Access-Control-Allow-Origin", "*"); //important, otherwise its not working 
    return "some text";
 });

На стороне клиента мне пришлось добавить это в запрос:

Ext.Ajax.request({
    url: "http://localhost:4567/someRestCallToSpark",
    useDefaultXhrHeader: false, //important, otherwise its not working
    success: function(response, opts) {console.log("success")},
    failure: function(response, opts) {console.log("failure")}
});
  • 0
    Имел ту же архитектуру, следовательно, ту же проблему, и это решало ее.
  • 3
    Это не очень хорошая идея, чтобы разрешать запросы из любого домена. Вы должны ограничить его только доверенным доменом.
Показать ещё 1 комментарий
8

У меня возникла проблема с этим, когда я использовал AngularJS для доступа к моему API. Тот же запрос работал в SoapUI 5.0 и ColdFusion. Мой метод GET уже имел заголовок Access-Control-Allow-Origin.

Я узнал, что AngularJS делает "пробный" запрос OPTIONS. ColdFusion, по умолчанию, генерирует метод OPTIONS, но в нем не так много, эти заголовки специально. Ошибка возникла в ответ на этот вызов OPTIONS, а не на мой намеренный вызов GET. После того, как я добавил метод OPTIONS ниже в свой API, проблема была решена.

<cffunction name="optionsMethod" access="remote" output="false" returntype="any" httpmethod="OPTIONS" description="Method to respond to AngularJS trial call">
    <cfheader name="Access-Control-Allow-Headers" value="Content-Type,x-requested-with,Authorization,Access-Control-Allow-Origin"> 
    <cfheader name="Access-Control-Allow-Methods" value="GET,OPTIONS">      
    <cfheader name="Access-Control-Allow-Origin" value="*">      
    <cfheader name="Access-Control-Max-Age" value="360">        
</cffunction>
  • 5
    Это не то, что делает запрос OPTIONS, это браузер, основанный на запросе!
  • 1
    Narretz - вызов API через браузер не вызывает этой ошибки и не вызывает вызов дополнительных опций. Когда используется угловой, это делает.
Показать ещё 1 комментарий
7

https://github.com/Rob--W/cors-anywhere/ предоставляет (Node.js) код, который вы можете использовать для настройки и запуска собственного прокси-сервера CORS. Он активно поддерживается и предоставляет ряд функций для управления прокси-поведением за пределами простой отправки правильных заголовков ответов Access-Control-*.

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS содержит подробные сведения о том, как браузеры обрабатывают запросы кросс-происхождения, которые клиентские веб-приложения создают из JavaScript и какие заголовки вы должны настроить отправку сервером запроса, если вы можете.

В случае, когда сайт, на который нужно отправить запрос и получить ответ, не возвращает заголовок ответа Access-Control-Allow-Origin, браузеры всегда будут блокировать запросы кросс-происхождения, сделанные им непосредственно на вашем клиентском JavaScript-скрипте код от работы. И если сайт не тот, которым вы управляете, и можете настроить поведение, единственное, что будет работать в этом случае, - это проксирование запросов - либо через собственный прокси-сервер, который вы запускаете, либо через открытый прокси.

Как уже упоминалось в других комментариях, есть веские причины не доверять открытому прокси с вашими запросами. Тем не менее, если вы знаете, что делаете, и вы решаете, что открытый прокси работает для ваших нужд, https://cors-anywhere.herokuapp.com/ - это тот, который надежно доступен, активно поддерживается, и он запускает экземпляр https://github.com/Rob--W/cors-anywhere/.

Как и в случае с другими открытыми прокси-серверами, упомянутыми здесь (пара, по крайней мере, кажется, больше недоступна), способ, которым он работает, заключается в том, что вместо того, чтобы ваш клиентский код отправлял запрос напрямую, например, http://foo.com, вы отправьте его в https://cors-anywhere.herokuapp.com/http://foo.com, и прокси добавит необходимые заголовки Access-Control-* в ответ, который видит браузер.

7

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

var yql_url = 'https://query.yahooapis.com/v1/public/yql';
var url = 'your api url';

$.ajax({
    'url': yql_url,
    'data': {
        'q': 'SELECT * FROM json WHERE url="'+url+'"',
        'format': 'json',
        'jsonCompat': 'new',
    },
    'dataType': 'jsonp',
    'success': function(response) {
        console.log(response);
    },
});

Здесь ссылка с объяснением: https://vverma.net/fetch-any-json-using-jsonp-and-yql.html

  • 0
    но через несколько секунд все остальные коды запускаются, а затем инициализируются.
5

В моем случае я использовал приложение JEE7 JAX-RS, и следующие трюки отлично работали для меня:

@GET
    @Path("{id}")
    public Response getEventData(@PathParam("id") String id) throws FileNotFoundException {
        InputStream inputStream = getClass().getClassLoader().getResourceAsStream("/eventdata/" + id + ".json");
        JsonReader jsonReader = Json.createReader(inputStream);
        return Response.ok(jsonReader.readObject()).header("Access-Control-Allow-Origin", "*").build();
    }
5

Если вы используете Entity Framework, кажется, что эта ошибка иногда возникает, даже если у вас включен CORS. Я понял, что ошибка произошла из-за отсутствия завершения запроса. Я надеюсь, что это поможет другим в той же ситуации.

В следующем коде может произойти ошибка XMLHttpRequest cannot load http://myApiUrl/login. No 'Access-Control-Allow-Origin' header is present on the requested resource.:

using (DBContext db = new DBContext())
{
    return db.Customers.Select(x => new
    {
        Name = x.Name,
        CustomerId = x.CustomerId,
    });
}

Чтобы исправить это, требуется завершить финализацию, например, .ToList() или .FirstOrDefault() в конце запроса, например:

using (DBContext db = new DBContext())
{
    return db.Customers.Select(x => new
    {
        Name = x.Name,
        CustomerId = x.CustomerId,
    }).ToList();
}
  • 1
    Это похоже на ошибку, которая произойдет в любом приложении структуры сущностей, если вы не завершите запрос. На самом деле не связано с CORS или вопросом ОП.
  • 2
    Вполне возможно, что он не связан с CORS, но выдает ошибку, которая звучит так, как будто она имеет отношение к CORS; отсюда мой ответ.
4

Для API GoLang:

Сначала вы можете посмотреть MDN CORS Doc, чтобы узнать, что такое CORS. Насколько я знаю, CORS говорит о том, разрешать ли Origin Request доступ к ресурсу сервера или нет.

И вы можете ограничить, какой источник запроса может получить доступ к серверу, установив Access-Control-Allow-Origin в Header ответа сервера.

Например, установка следующего заголовка в ответе сервера означает, что только запрос, отправленный из http://foo.example, может получить доступ к вашему серверу:

Access-Control-Allow-Origin: http://foo.example

и затем разрешить запрос, отправленный из любого источника (или домена):

Access-Control-Allow-Origin: *

И как я знаю в сообщении об ошибке, requested resource означает ресурс сервера, поэтому No 'Access-Control-Allow-Origin' header is present on the requested resource. означает, что вы не установили заголовок Access-Control-Allow-Origin в вашем ответе сервера, или, может быть, вы установили, но источник запроса isn ' t в Access-Control-Allow-Origin, поэтому запрос не допускается:

Нет заголовка "Access-Control-Allow-Origin" присутствует на запрошенном ресурсе. Поэтому исходный "null" не допускается.

В GoLang я использую пакет gorilla/mux для сборки сервера API в localhost:9091, и я разрешаю CORS путем добавления "Access-Control-Allow-Origin", "*" в заголовок ответа:

func main() { // API Server Code
    router := mux.NewRouter()
    // API route is /people,
    //Methods("GET", "OPTIONS") means it support GET, OPTIONS
    router.HandleFunc("/people", GetPeople).Methods("GET", "OPTIONS")
    log.Fatal(http.ListenAndServe(":9091", router))
}

// Method of '/people' route
func GetPeople(w http.ResponseWriter, r *http.Request) {

    // Allow CORS by setting * in sever response
    w.Header().Set("Access-Control-Allow-Origin", "*")

    w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
    json.NewEncoder(w).Encode("OKOK")
}

И я использую JavaScript в клиенте, в localhost:9092 сделать запрос от Chrome может успешно получить "OKOK" с сервера localhost:9091.

function GetPeople() {
    try {
        var xhttp = new XMLHttpRequest();
        xhttp.open("GET", "http://localhost:9091/people", false);
        xhttp.setRequestHeader("Content-type", "text/html");
        xhttp.send();
        var response = JSON.parse(xhttp.response);
        alert(xhttp.response);
    }
    catch (error) {
        alert(error.message);
    }
}

Кроме того, вы можете проверить свой заголовок запроса/ответа с помощью таких инструментов, как Fiddler.

4

Если вы получите это сообщение об ошибке в браузере:

No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin '…' is therefore not allowed access

когда вы пытаетесь выполнить запрос AJAX POST/GET удаленному серверу, который вышел из-под контроля, забудьте об этом простом исправлении:

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

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

Сначала в своем JavaScript-коде выполните вызов Ajax на ваш собственный сервер, например:

$.ajax({
    url: yourserver.com/controller/proxy.php,
    async: false,
    type: "POST",
    dataType: "json",
    data: data,
    success: function (result) {
        JSON.parse(result);
    },
    error: function (xhr, ajaxOptions, thrownError) {
        console.log(xhr);
    }
});

Затем создайте простой PHP файл с именем proxy.php, чтобы обернуть ваши данные POST и добавить их на удаленный URL-сервер в качестве параметров. Я приведу пример того, как я обойду эту проблему с API поиска Expedia:

if (isset($_POST)) {
  $apiKey = $_POST['apiKey'];
  $cid = $_POST['cid'];
  $minorRev = 99;

  $url = 'http://api.ean.com/ean-services/rs/hotel/v3/list?' . 'cid='. $cid . '&' . 'minorRev=' . $minorRev . '&' . 'apiKey=' . $apiKey;

  echo json_encode(file_get_contents($url));
 }

Выполняя:

echo json_encode(file_get_contents($url));

Вы просто выполняете тот же запрос, но на стороне сервера, и после этого он должен работать нормально.

Ответ скопирован и вставлен из NizarBsb

Показать ещё 1 комментарий
4

Популярный вопрос - Еще одна вещь, на которую нужно смотреть, если вы читали это далеко, и ничего больше не помогло. Если у вас есть CDN, например Akamai, Limelight или подобное, вы можете проверить ключ кеша, который у вас есть для URI ресурса. Если он не содержит значение заголовка Origin, вы можете вернуть ответ в кешированный запрос по другому источнику. Мы просто потратили полдня на отладку. Конфигурация CDN была обновлена, чтобы включать только значение Origin для нескольких выбранных доменов, которые являются нашими, и установить для него значение null для всех остальных. Это похоже на работу и позволяет браузерам из наших известных доменов просматривать наши ресурсы. Конечно, все остальные ответы являются предпосылками для получения здесь, но если CDN является первым переходом из вашего браузера, это то, что нужно рассмотреть.

В нашем случае мы могли видеть, как некоторые запросы поступают к нашему сервису, но не почти по объему, который отправлял сайт. Это указывало нам на CDN. Мы смогли вернуться и посмотреть, что исходный запрос был подан с помощью прямого запроса, а не части вызова AJAX браузера, и заголовок ответа Access-Control-Allow-Origin не был включен. По-видимому, CDN кэшировал это значение. Конфигурация конфигурации Akamai CDN, чтобы рассмотреть значение заголовка запроса Origin как часть совпадения, похоже, заставило его работать для нас.

  • 1
    В вашем случае, разве отправка заголовка ответа Vary: Origin не достигла такого же эффекта? stackoverflow.com/questions/46063304/...
  • 2
    Да, но мы не делаем. Служба, доступная миру, может быть DOS'а через взлом кеша путем отправки поддельных значений. Akamai имеет некоторую помощь в этой области, чтобы уменьшить воздействие DOS. Я хочу сказать, что вы можете делать все, что перечислено, и все еще иметь проблемы из-за кеширования.
Показать ещё 3 комментария
4

Я успешно смог решить (в моем случае для шрифтов) использовать htaccess, но, очевидно, OP задает немного разные. Но вы можете использовать шаблон FileMatch и добавлять любое расширение, чтобы он не выдавал ошибку cros.

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

https://httpd.apache.org/docs/2.4/mod/core.html#filesmatch

3

Много раз это происходит со мной от javascript к моему php api, потому что одна из нескольких причин. Я забыл поставить <?php header('Access-Control-Allow-Origin: *'); ? один. Это полезно для доступа к перекрестным доменам. Другая причина заключается в том, что в jQuery ajax-запросе я указываю конкретный тип данных и возвращаю другой тип данных, поэтому он выдает ошибку.

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

Надеюсь, это поможет кому-то. Мне потребовалось некоторое время, чтобы отладить это, и я бы хотел, чтобы у меня был контрольный список вещей для проверки.

2

в случае, если вы хотите исправить это на бэкэнд (в Flask), а не на лицевой стороне, я бы полностью рекомендовал пакет POS-пакетов Flask CORS. Фляги Корс

С помощью одной простой строки в app.py вы можете автоматически вставить стандарт, разрешить любой заголовок источника, или настроить его по мере необходимости.

2

Большинство этих ответов говорят пользователям, как добавить заголовки CORS на сервер, который они контролируют.

Однако, если вам нужны данные с сервера, который вы не контролируете на веб-странице, одним из решений является создание тега script на вашей странице, установите атрибут src в конечную точку api, у которой нет заголовков CORS, затем загрузите эти данные на страницу:

  window.handleData = function (data) { console.log(данные)
};

var script= document.createElement('script');
script.setAttribute( 'SRC', 'HTTPS://some.api/without/cors/headers.com& обратный вызов = handleData');
document.body.appendChild(сценарий);
Код>
  • 0
    Отличный ответ, но если скрипт не в правильном формате, вы не можете получить его код (script.text = empty). Что делать в этом случае? Как добраться до его кода?
  • 0
    Как предотвратить выполнение скрипта (может быть, как все это прокомментировать)?
Показать ещё 1 комментарий
2

Для полноты Apache разрешает cors:

Header set Access-Control-Allow-Origin "http://www.allowonlyfromthisurl.com"
Header set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header set Access-Control-Max-Age "1000"
Header set Access-Control-Allow-Headers "x-requested-with, Content-Type, Accept-Encoding, Accept-Language, Cookie, Referer"
  • 0
    Любой может добавить к этому ^
  • 0
    Работал на Apache и Laravel 5.4
2

На моем веб-сайте (на основе .NET) я только что добавил это:

<system.webServer>
 <httpProtocol>  
    <customHeaders>  
     <add name="Access-Control-Allow-Origin" value="*" />  
     <add name="Access-Control-Allow-Headers" value="Content-Type" />  
     <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />  
    </customHeaders>  
  </httpProtocol>         
</system.webServer>

Большое спасибо это видео.

  • 1
    В вопросе говорится: «Я знаю, что API или удаленный ресурс должен устанавливать заголовок, но почему он работал, когда я делал запрос через расширение Chrome Postman?». Это не ответ на вопрос, который был задан.
2

Я получил эту ошибку с $http.get в Angular. Мне нужно было использовать $http.jsonp.

2

CORS для вас.

CORS - это совместное использование ресурсов Cross Origin, и это способ отправки запроса междоменного доступа. Теперь API XMLHttpRequest2 и Fetch поддерживают CORS.

Но он имеет свои пределы. Серверу требуется конкретное требование Access-Control-Allow-Origin, и его нельзя установить в '*'.

И если вы хотите, чтобы любое происхождение могло отправить вам запрос, вам нужен JSONP (также нужно установить Access-Control-Allow-Origin, но может быть "*" ).

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


Если вы используете современный браузер ( > Internet Explorer9, Chrome, Firefox, Edge и т.д.), очень рекомендуется использовать простой, но красивый компонент, https://github.com/Joker-Jelly/catta. Он не имеет зависимостей, составляет менее 3 килобайт, и он поддерживает Fetch, Ajax и JSONP с такими же простыми синтаксисами и параметрами.

catta('./data/simple.json').then(function (res) {
  console.log(res);
});

Он также поддерживает весь способ импорта в ваш проект, например, модуль ES6, CommonJS и даже <script> в HTML.

  • 0
    У меня есть локальный сайт IIS, на котором размещен мой API. У меня есть внешний сайт, доступ к которому осуществляется за пределами локальной сети. Я пытаюсь выполнить API с внешнего сайта, у меня включен CORS для внешнего сайта (например, [EnableCors(origins: "http://websitelink.com", headers: "*", methods: "*")] но это не работает. Любая идея? forums.asp.net/p/2117965/…
1

В запросе jsonp вы должны поймать "jsonpCallback" и отправить его обратно.

$.ajax({
      url: lnk,
      type: 'GET',
      crossDomain: true,
      dataType: 'jsonp',
      success: function (ip) { console.log(ip.ip); },
      error: function (err) { console.log(err) }
});

На стороне сервера (если вы используете в качестве backend PHP)

echo $_GET['callback'].'({"ip":"192.168.1.1"})';

В этом случае backend-ответ кажется

jQuery331009526199802841284_1533646326884 ({ "ф": "192.168.1.1"})

но вы можете установить "jsonpCallback" вручную на интерфейсе и поймать его на стороне сервера

$.ajax({
      url: lnk,
      type: 'GET',
      crossDomain: true,
      dataType: 'jsonp',
      jsonpCallback: 'get_ip',
      success: function (ip) { console.log(ip.ip); },
      error: function (err) { console.log(err) }
});

В этом случае backend-ответ кажется

get_ip ({ "ф": "192.168.1.1"})

1

Возможно, это немного сложнее, но вы можете использовать веб-сервер для маршрутизации запроса. С nodejs вы не имеете этой проблемы. Я не эксперт в узле js. Поэтому я не знаю, является ли это чистым кодом.

Но это работает для меня

Вот несколько примеров:

NODE JS

var rp = require('request-promise');
var express = require('express'),
    app = express(),
    port = process.env.PORT || 3000;
var options = {
    method: 'POST',
    uri: 'http://api.posttestserver.com/post',
    body: {
        some: 'payload'
    },
    json: true // Automatically stringifies the body to JSON
};
app.get('/', function (req, res) {
        rp(options)
        .then(function (parsedBody) {
            res.send(parsedBody)
        })
        .catch(function (err) {
            res.send(err)
        });
});
app.listen(port);

JS

axios.get("http://localhost:3000/").then((res)=>{
    console.log('================res====================');
    console.log(res);
    console.log('====================================');
})
1

Нет заголовка "Access-Control-Allow-Origin" присутствует на запрошенном ресурсе. Origin 'https://sx.xyz.com', следовательно, не допускается.

Я столкнулся с аналогичной проблемой с Exchange Domain Exchange в ответе Ajax как ошибка undefined. Но ответ в заголовке был Код состояния: 200 OK

  Не удалось загрузить https://www.Domain.in/index.php?route=api/synchronization/checkapikey:
В запрошенном ресурсе нет заголовка  "Access-Control-Allow-Origin".
Следовательно, для источника https://sx.xyz.in 'не разрешен доступ.
Код>

Решение обойти это: В моем случае нужно было вызвать функцию checkapikey() через Ajax в другой домен и получить ответ с данными, где был сделан вызов:

  if (($ this- > request- > server ['REQUEST_METHOD'] == 'POST') && isset ($ this- > request- > server ['HTTP_ORIGIN' ])) {
       $ this- > response- > addHeader ('Access-Control-Allow-Origin:'. $this- > request- > server ['HTTP_ORIGIN']);       $ this- > response- > addHeader ('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');       $ this- > response- > addHeader ( "Access-Control-Max-Age: 1000" );       $ this- > response- > addHeader ('Access-Control-Allow-Credentials: true');       $ this- > response- > addHeader ( "Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With" );
       $ headers = getallheaders();
...
}
Код>
1

Для сервера Ruby on Rails в application_controller.rb добавьте следующее:

after_action :cors_set_access_control_headers

def cors_set_access_control_headers
  headers['Access-Control-Allow-Origin'] = '*'
  headers['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS'
  headers['Access-Control-Allow-Headers'] = '*'
end
  • 1
    В вопросе говорится: «Я знаю, что API или удаленный ресурс должен устанавливать заголовок, но почему он работал, когда я делал запрос через расширение Chrome Postman?». Это не ответ на вопрос, который был задан.
0

Я создал простой мост в своем собственном домене, который выбирает и показывает контент из внешнего домена.

<?php
header("Content-Type: text/plain");
if (isset($_GET["cnic"]))
{
    $page = file_get_contents("https://external.domain.com/api/verify/" . $_GET["cnic"]);
    echo $page;
}
else
{
    echo "";
}

?>

Теперь вместо доступа к внешнему домену в AJAX я разместил URL этого файла моста.

0

Возможно, вы не захотите использовать Jsonp, потому что он имеет некоторые ограничения, например, не поддерживает метод POST.

Вам просто нужно включить CORS на вашем сервере.

Если вы используете весеннюю загрузку, прочитайте этот пост: https://spring.io/guides/gs/rest-service-cors/

Короче говоря, просто положить:

@CrossOrigin(origins = "*")

перед вашей аннотацией @RequestMapping.

  • 0
    Я использую AngularJS и Spring на локальном хосте (разные порты), и у меня была та же проблема, добавление @CrossOrigin (origins = "*"), как указано ниже, решило ее.
0

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

0

Просто упомянем еще один способ "обойти" его - прокси AJAX. Отправьте запрос на ваш сервер, чтобы получить данные из другого источника и отправить запрос обратно.

Я предпочитаю этот подход над JSONP, потому что у него есть некоторые потенциальные проблемы с безопасностью.

  • 0
    В вопросе говорится: «Я знаю, что API или удаленный ресурс должен устанавливать заголовок, но почему он работал, когда я делал запрос через расширение Chrome Postman?». Это не ответ на вопрос, который был задан.
0

Для Opera (он работает так же, как Chrome), Я начал браузер с помощью этой команды:

opera --user-data-dir="~/Downloads/opera-session" --disable-web-security

Проблема решена! Теперь я могу работать с локальным файлом HTML (на моем жестком диске) и вызывать запросы Ajax для удаленного источника в том же файле.

Примечание 1: Вы можете указать любую папку в своем домашнем каталоге как -user-data-dir.

Примечание 2: Протестировано на Debian 8 (Jessie)/Opera 39

Изображение 2062

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

0

Я разрешил это, включив CORS для URL-адреса клиента, обращающегося к веб-API, и он успешно работал.

Например:

[EnableCors(origins: "http://clientaccessingapi.com", headers: "*", methods: "*")]
-1

Пожалуйста, добавьте dataType: 'jsonp' в функцию Ajax, и он работает. (


    $.ajax({
      type: "POST",
      dataType: 'jsonp',
      success: function(response) {
        alert("success");
      },
      error: function(response) {
        console.log(JSON.stringify(response));
      }
    });

  • 0
    Не работает на Chrome
  • 0
    @ OmarKhazamov да, это так.
Показать ещё 3 комментария
-5

Я попробовал следующее решение. Этот метод работает только тогда, когда ваш сервер работает локально.

  • Поместите следующую строку в файл web.xml.

    <filter>
        <filter-name>CORS</filter-name>
        <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CORS</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
  • Загрузите cors-filter-2.1.2 и java-property- utils-1.9.1 и поместить в библиотеку
  • Откройте браузер, чтобы разрешить управление доступом с помощью следующего кода в терминале (Mac)

    /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --allow-file-access-from-files
    

Ещё вопросы

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