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

Я пытаюсь выполнить авторизацию с помощью 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);
    });

63 ответа

Решение

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

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

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

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

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

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

Предупреждение: это содержит проблему безопасности для вашего PHP-файла, которая может быть вызвана злоумышленниками. Вы должны использовать сеансы и куки для аутентификации, чтобы предотвратить ваш файл / сервис от этой атаки. Ваш сервис уязвим для подделки межсайтовых запросов (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"
},

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

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

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

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

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

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

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

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

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

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

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

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

В приведенном ниже исследовании в качестве API я использую http://example.com/ вместо http://myapiurl/login из вашего вопроса, потому что этот первый работает.

Я предполагаю, что ваша страница находится на http://my-site.local:8088/ .

Причина, по которой вы видите разные результаты, заключается в том, что Почтальон:

  • установить заголовок Host=example.com (ваш API)
  • НЕ устанавливать заголовок Origin

Это похоже на способ отправки запросов браузерами, когда сайт и API имеют один и тот же домен (браузеры также устанавливают элемент заголовка Referer=http://my-site.local:8088, но в Postman я этого не вижу). когдаOriginзаголовок не установлен, обычно серверы разрешают такие запросы по умолчанию.

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

  • устанавливает заголовок Host=example.com (ваш как API)
  • устанавливает заголовок Origin=http://my-site.local:8088 (твой сайт)

(Заголовок Referer имеет то же значение, что и Origin). И теперь во вкладке Chrome Console & Networks вы увидите:

Когда у тебя есть Host != Origin это CORS, и когда сервер обнаруживает такой запрос, он обычно блокирует его по умолчанию.

Origin=nullустанавливается, когда вы открываете HTML-контент из локального каталога и отправляет запрос. Такая же ситуация, когда вы отправляете запрос внутри<iframe>, как в приведенном ниже фрагменте (но здесь Host заголовок не задан вообще) - в общем, везде, где в спецификации HTML указано непрозрачное происхождение, вы можете перевести это как Origin=null. Более подробную информацию об этом вы можете найти здесь.

fetch('http://example.com/api', {method: 'POST'});
Look on chrome-console > network tab

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

fetch('http://example.com/api', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json'}
});
Look in chrome-console -> network tab to 'api' request.
This is the OPTIONS request (the server does not allow sending a POST request)

Вы можете изменить конфигурацию своего сервера, чтобы разрешить запросы CORS.

Вот пример конфигурации, которая включает CORS на nginx (файл nginx.conf) - будьте очень осторожны с настройкойalways/"$http_origin" для nginx и "*" для Apache - это разблокирует CORS из любого домена.

location ~ ^/index\.php(/|$) {
   ...
    add_header 'Access-Control-Allow-Origin' "$http_origin" always;
    add_header 'Access-Control-Allow-Credentials' 'true' always;
    if ($request_method = OPTIONS) {
        add_header 'Access-Control-Allow-Origin' "$http_origin"; # DO NOT remove THIS LINES (doubled with outside 'if' above)
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Max-Age' 1728000; # cache preflight value for 20 days
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'My-First-Header,My-Second-Header,Authorization,Content-Type,Accept,Origin';
        add_header 'Content-Length' 0;
        add_header 'Content-Type' 'text/plain charset=UTF-8';
        return 204;
    }
}

Вот пример конфигурации, которая включает CORS на Apache (файл.htaccess)

# ------------------------------------------------------------------------------
# | Cross-domain Ajax requests                                                 |
# ------------------------------------------------------------------------------

# Enable cross-origin Ajax requests.
# http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity
# http://enable-cors.org/

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

# Header set Header set Access-Control-Allow-Origin "*"
# Header always set Access-Control-Allow-Credentials "true"

Access-Control-Allow-Origin "http://your-page.com:80"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header always set Access-Control-Allow-Headers "My-First-Header,My-Second-Header,Authorization, content-type, csrf-token"

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

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

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

Применение ограничения CORS - это функция безопасности, определяемая сервером и реализуемая браузером.

Браузер смотрит на политику CORS сервера и уважает ее.

Однако инструмент Postman не заботится о политике CORS сервера.

Поэтому ошибка CORS появляется в браузере, а не в Postman.

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

The CORS standard is a client-side standard, implemented in the browser. So it is the browser which prevent the call from completing and generates the error message - not the server.

Postman does not implement the CORS restrictions, which is why you don't see the same error when making the same call from Postman.

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

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

Истоки решения и проблемы

Вы делаете XMLHttpRequest для разных доменов, например:

  1. Домен один: some-domain.com
  2. Второй домен: some-different-domain.com

Эта разница в именах доменов запускает политику CORS ( ), называемую SOP (Cross-Origin Resource SharingSame-Origin Policy ), которая обеспечивает использование одних и тех же доменов (следовательно , Origin ) в Ajax, XMLHttpRequest и других HTTP-запросах.

Почему это сработало, когда я сделал запрос через расширение Postman для Chrome?

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

Большинство браузеров применяют политику Same-Origin Policy для предотвращения проблем, связанных с атакой CSRF (подделка межсайтовых запросов ).

Postman как инструмент разработки предпочитает не применять SOP, в то время как некоторые браузеры применяют его, поэтому вы можете отправлять запросы через Postman, которые вы не можете отправить с помощью XMLHttpRequest через JS с помощью браузера.

Если вы хотите обойти это ограничение при получении содержимого с помощью fetch API или XMLHttpRequest в javascript, вы можете использовать прокси-сервер, чтобы он устанавливал заголовок Access-Control-Allow-Origin к *.

const express = require('express');
const request = require('request');

const app = express();

app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*');
  next();
});

app.get('/fetch', (req, res) => {
  request(
    { url: req.query.url },
    (error, response, body) => {
      if (error || response.statusCode !== 200) {
        return res.status(500).send('error');
      }
      res.send(body);
    }
  )
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`listening on ${PORT}`));

Выше приведен пример кода (требуется узел Js), который может действовать как прокси-сервер. Например: если я хочу получитьhttps://www.google.com обычно возникает ошибка CORS, но теперь, поскольку запрос отправляется через прокси-сервер, размещенный локально на порте 3000, прокси-сервер добавляет Access-Control-Allow-Origin заголовок в ответе, и проблем не будет.

Отправьте запрос GET на http://localhost:3000/fetch? Url=Your URL here вместо того, чтобы напрямую отправлять запрос в URl, который вы хотите получить.

Your URL here обозначает URL-адрес, который вы хотите получить, например: https://www.google.com

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

Пример использования: в хроме при попытке вызвать конечную точку Spring REST в angular.

https://stackru.com/image s/c9ce3581bb4ac561d8341b555b66e70162054eb3.png

Решение: добавьте аннотацию @CrossOrigin("*") поверх соответствующего класса контроллера.

https://stackru.com/image s/4a6958ab59b00b8ee590b3beaf2e4b759a2c939f.png

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

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

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

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

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

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

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

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

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

На стороне сервера: 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")}
});

У меня была проблема с этим, когда я использовал 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>

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

В целях тестирования браузера:Windows — выполнить:

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

Вы также можете получить эту ошибку, если тайм-аут вашего шлюза слишком короткий, а ресурс, к которому вы обращаетесь, требует больше времени для обработки, чем тайм-аут. Это может иметь место для сложных запросов к базе данных и т. д. Таким образом, приведенный выше код ошибки может скрывать эту проблему. Просто проверьте, является ли код ошибки 504 вместо 404, как в ответе Камилса выше, или что-то еще. Если это 504, то увеличение времени ожидания шлюза может решить проблему.

В моем случае ошибку CORS можно было устранить, отключив ту же политику происхождения (CORS) в браузере IE, см. Как отключить ту же политику происхождения в Internet Explorer . После этого в журнале была чистая ошибка 504.

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/ code.

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

Если вы используете 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();
}

В моем случае я использовал приложение 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();
    }

Только для проекта.NET Core Web API добавьте следующие изменения:

  1. Добавьте следующий код после services.AddMvc() линия в ConfigureServices() метод файла Startup.cs:
services.AddCors(allowsites=>{allowsites.AddPolicy("AllowOrigin", options => options.AllowAnyOrigin());
            });
  1. Добавьте следующий код после app.UseMvc() линия в Configure() метод файла Startup.cs:
app.UseCors(options => options.AllowAnyOrigin());
  1. Откройте контроллер, к которому вы хотите получить доступ за пределами домена, и добавьте следующий атрибут на уровне контроллера:
[EnableCors("AllowOrigin")]

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

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 Hotel:

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

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

Ответ скопирован и вставлен из Nizar B.

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

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

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

<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

Другие вопросы по тегам