jquery - ошибка - xmlhttprequest access control allow origin




Почему мой JavaScript получает заголовок «Нет» Access-Control-Allow-Origin? Присутствует на ошибке запрашиваемого ресурса, когда почтальон не делает этого? (20)

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

XMLHttpRequest не может загрузить http: // myApiUrl / login . В запрошенном ресурсе нет заголовка «Access-Control-Allow-Origin». Поэтому исходный 'null' не допускается.

Я знаю, что API или удаленный ресурс должен установить заголовок, но почему он работал, когда я сделал запрос через расширение 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);
    });

Это не исправление для производства или когда приложение должно быть показано клиенту, это полезно только тогда, когда разработка UI и Backend на разных серверах и в процессе производства они фактически находятся на одном сервере. Например: при разработке пользовательского интерфейса для любого приложения, если есть необходимость протестировать его локально, указывая на сервер бэкэнд, в этом случае это идеальное решение. Для исправления производства заголовки 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» .


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

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


Вы можете обойти эту проблему, используя 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


Для GoLang API:

Сначала вы можете взглянуть на MDN CORS Doc, чтобы узнать, что такое CORS. Насколько я знаю, CORS говорит о том, разрешать ли Origin of 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 в своем ответе на сервер или, может быть, вы установили, но источник запроса не указан в 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 .


Если вы используете 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 on ExpressJS


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

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

Узнайте больше о работе с JSONP here :

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


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

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


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

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

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


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

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


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

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


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

Я узнал, что AngularJS делает запрос пробных запросов . 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>

Это очень просто решить, если вы используете 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"
},

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

Все, что тебе нужно:

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


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

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

В случае, когда сайт, на который вы хотите отправить запрос и получить ответ, не возвращает заголовок ответа Access-Control-Allow-Origin , браузеры всегда будут блокировать запросы кросс-происхождения, сделанные им непосредственно вашим клиентом -side 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-* в ответ, который видит браузер.


В запрошенном ресурсе нет заголовка «Access-Control-Allow-Origin». Происхождение « https://sx.xyz.com », следовательно , не имеет права доступа.

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

Failed to load https://www.Domain.in/index.php?route=api/synchronization/checkapikey:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'https://sx.xyz.in' is therefore not allowed access.

Решение обойти это: в моем случае нужно было вызвать функцию 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();
...
}

CORS для вас.

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

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

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

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

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

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

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


На моем веб-сайте (на основе .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>

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


Возможно, это немного сложнее, но вы можете использовать веб-сервер для маршрутизации запроса. С 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('====================================');
})

Для сервера 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

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

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

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





flask-restless