Как работает заголовок Access-Control-Allow-Origin?

Видимо, я совершенно не понял ее семантику. Я думал о чем-то вроде этого:

  1. Клиент загружает код JavaScript MyCode.js с http://siteA - источник.
  2. Заголовок ответа MyCode.js содержит Access-Control-Allow-Origin: http: // siteB, что, как я думал, означало, что MyCode.js было разрешено делать ссылки на сайт B.
  3. Клиент запускает некоторые функциональные возможности MyCode.js, которые, в свою очередь, отправляют запросы на http://siteB, что должно быть хорошо, несмотря на то, что это запросы между источниками.

Ну, я не прав. Это не работает, как это вообще. Итак, я прочитал разделение ресурсов между источниками и попытался прочитать разделение ресурсов между источниками в рекомендации w3c

Одно можно сказать наверняка - я до сих пор не понимаю, как я должен использовать этот заголовок.

У меня есть полный контроль над сайтом A и сайтом B. Как включить код JavaScript, загруженный с сайта A, для доступа к ресурсам на сайте B с помощью этого заголовка?

PS

Я не хочу использовать JSONP.

21 ответ

Решение

Access-Control-Allow-Origin является заголовком CORS (Cross-Origin Resource Sharing)

Когда сайт A пытается извлечь контент с сайта B, сайт B может отправить Access-Control-Allow-Origin заголовок ответа, чтобы сообщить браузеру, что содержание этой страницы доступно для определенных источников. (Источник - это домен, а также схема и номер порта.) По умолчанию страницы сайта B недоступны для любого другого источника; с использованием Access-Control-Allow-Originзаголовок открывает дверь для перекрестного доступа по конкретным запрашивающим источникам.

Для каждого ресурса / страницы, которые Сайт B хочет сделать доступными для Сайта A, Сайт B должен обслуживать свои страницы с заголовком ответа:

Access-Control-Allow-Origin: http://siteA.com

Современные браузеры не будут блокировать междоменные запросы напрямую. Если сайт A запрашивает страницу с сайта B, браузер фактически извлекает запрошенную страницуна сетевом уровне и проверяет, содержит ли заголовки ответа сайт A в качестве разрешенного домена запрашивающей стороны. Если сайт B не указал, что сайту A разрешен доступ к этой странице, браузер вызовет XMLHttpRequest"serror событие и запретить данные ответа запрашивающему коду JavaScript.

Не простые запросы

То, что происходит на уровне сети, может бытьнемного сложнее, чем объяснено выше. Если запрос является "непростым" запросом, браузер сначала отправляет запрос"предварительных полетов" OPTIONS без данных, чтобы убедиться, что сервер примет запрос. Запрос является непростым, когда либо (или оба):

  • используя HTTP-глагол, отличный от GET или POST (например, PUT, DELETE)
  • использование непростых заголовков запросов; заголовки простых запросов:
    • Accept
    • Accept-Language
    • Content-Language
    • Content-Type (это просто, когда его значение application/x-www-form-urlencoded, multipart/form-data, или же text/plain)

Если сервер отвечает на предварительный просмотр OPTIONS с соответствующими заголовками ответа (Access-Control-Allow-Headers для непростых заголовков, Access-Control-Allow-Methods для непростых глаголов), которые соответствуют непростым глаголам и / или непростым заголовкам, тогда браузер отправляет фактический запрос.

Предположим, что сайт А хочет отправить запрос PUT для /somePageс непростым Content-Type ценность application/jsonбраузер сначала отправит предварительный запрос:

OPTIONS /somePage HTTP/1.1
Origin: http://siteA.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Content-Type

Обратите внимание, что Access-Control-Request-Method а также Access-Control-Request-Headers добавляются браузером автоматически; Вам не нужно добавлять их. Этот предварительный просмотр OPTIONS получает заголовки успешного ответа:

Access-Control-Allow-Origin: http://siteA.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: Content-Type

При отправке фактического запроса (после выполнения предварительной проверки) поведение идентично тому, как обрабатывается простой запрос. Другими словами, непростой запрос, предпечатная проверка которого успешна, обрабатывается так же, как простой запрос (т. Е. Сервер все еще должен отправить Access-Control-Allow-Origin снова за фактический ответ).

Браузеры отправляют актуальный запрос:

PUT /somePage HTTP/1.1
Origin: http://siteA.com
Content-Type: application/json

{ "myRequestContent": "JSON is so great" }

И сервер отправляет обратно Access-Control-Allow-Originтак же, как и для простого запроса:

Access-Control-Allow-Origin: http://siteA.com

Посмотрите Понимание XMLHttpRequest через CORS для немного больше информации о непростых запросах.

Обмен запросами между источниками - CORS (Междоменный AJAX-запрос AKA) - это проблема, с которой может столкнуться большинство веб-разработчиков. Согласно Same-Origin-Policy, браузеры ограничивают клиентский JavaScript в изолированной программной среде безопасности, обычно JS не может напрямую взаимодействовать с удаленным сервером из другого домена. В прошлом разработчики создавали множество хитрых способов достижения запроса к междоменным ресурсам, чаще всего с использованием следующих способов:

  1. Используйте Flash/Silverlight или серверную часть в качестве "прокси" для связи с удаленным.
  2. JSON с набивкой ( JSONP).
  3. Встраивает удаленный сервер в iframe и связывается через фрагмент или имя window.name, см. Здесь.

У этих хитрых способов есть более или менее некоторые проблемы, например, JSONP может привести к дыре в безопасности, если разработчики просто "оценят" ее, и № 3 выше, хотя это работает, оба домена должны заключать строгие контракты друг с другом, это ни гибко, ни элегантно ПО МОЕМУ МНЕНИЮ:)

W3C представила Cross-Origin Resource Sharing (CORS) в качестве стандартного решения, чтобы обеспечить безопасный, гибкий и рекомендуемый стандартный способ решения этой проблемы.

Механизм

На высоком уровне мы можем просто считать, что CORS - это контракт между клиентским вызовом AJAX из домена A и страницей, размещенной в домене B, типичный запрос / ответ Cross-Origin будет выглядеть так:

DomainA AJAX заголовки запроса

Host DomainB.com
User-Agent Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0) Gecko/20100101 Firefox/4.0
Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8,application/json
Accept-Language en-us;
Accept-Encoding gzip, deflate
Keep-Alive 115
Origin http://DomainA.com 

Заголовки ответа DomainB

Cache-Control private
Content-Type application/json; charset=utf-8
Access-Control-Allow-Origin DomainA.com
Content-Length 87
Proxy-Connection Keep-Alive
Connection Keep-Alive

Синие части, которые я отмечал выше, были фактами ядра, "заголовок запроса" Происхождение "указывает, откуда исходит перекрестный запрос или запрос предварительной проверки", заголовок ответа "Access-Control-Allow-Origin" указывает, что эта страница допускает удаленный запрос от DomainA (если значение * указывает, разрешает удаленные запросы из любого домена).

Как я упоминал выше, W3 рекомендовал браузеру реализовать предварительныйзапрос перед отправкой фактически HTTP-запроса Cross-Origin, в двух словах это HTTP OPTIONS запрос:

OPTIONS DomainB.com/foo.aspx HTTP/1.1

Если foo.aspx поддерживает HTTP-глагол OPTIONS, он может вернуть ответ, как показано ниже:

HTTP/1.1 200 OK
Date: Wed, 01 Mar 2011 15:38:19 GMT
Access-Control-Allow-Origin: http://DomainA.com
Access-Control-Allow-Methods: POST, GET, OPTIONS, HEAD
Access-Control-Allow-Headers: X-Requested-With
Access-Control-Max-Age: 1728000
Connection: Keep-Alive
Content-Type: application/json

Только если ответ содержит "Access-Control-Allow-Origin" И его значение равно "*" или содержит домен, который отправил запрос CORS, при выполнении этого обязательного условия браузер отправит фактический междоменный запрос и кеширует результат в "Preflight-Result-Cache".

Я писал о CORS три года назад: HTTP-запрос AJAX Cross-Origin

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

Согласно этой статье Mozilla Developer Network,

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

введите описание изображения здесь

HTML-страница подается с http://domain-a.com делает <img> запрос SRC для http://domain-b.com/image.jpg,
Сегодня многие страницы в Интернете загружают ресурсы, такие как таблицы стилей CSS, изображения и скрипты, из разных доменов (поэтому это должно быть круто).

Политика одного происхождения

По соображениям безопасности браузеры ограничивают перекрестные HTTP- запросы, инициируемые из сценариев.
Например, XMLHttpRequest а также Fetch следовать политике того же происхождения.
Итак, веб-приложение, использующее XMLHttpRequest или же Fetch мог только сделать HTTP-запросы к своему собственному домену.

Обмен ресурсами между источниками (CORS)

Чтобы улучшить веб-приложения, разработчики попросили поставщиков браузеров разрешить междоменные запросы.

Механизм общего доступа к ресурсам между источниками (CORS) предоставляет веб-серверам средства управления междоменным доступом, которые обеспечивают безопасную междоменную передачу данных.
Современные браузеры используют CORS в контейнере API - например, XMLHttpRequest или же Fetch - чтобы снизить риски перекрестных HTTP-запросов.

Как работает CORS (Access-Control-Allow-Origin заголовок)

Википедия:

Стандарт CORS описывает новые заголовки HTTP, которые обеспечивают браузерам и серверам способ запрашивать удаленные URL-адреса только при наличии разрешения.

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

пример

  1. Браузер отправляет OPTIONS запрос с Origin HTTP заголовок.

    Значением этого заголовка является домен, который обслуживал родительскую страницу. Когда страница из http://www.example.com пытается получить доступ к данным пользователя в service.example.com следующий заголовок запроса будет отправлен service.example.com:

    Происхождение: http://www.example.com/

  2. Сервер на service.example.com может ответить:

    • Access-Control-Allow-Origin (ACAO) заголовок в своем ответе, указывающий, какие сайты происхождения разрешены.
      Например:

      Access-Control-Allow-Origin: http://www.example.com

    • Страница с ошибкой, если сервер не разрешает перекрестный запрос

    • Access-Control-Allow-Origin (ACAO) заголовок с подстановочным знаком, который разрешает все домены:

      Access-Control-Allow-Origin: *

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

Цель той же политики происхождения - защитить вас от вредоносного JavaScript на siteA.com, который получает доступ к частной информации, которую вы выбрали для обмена только с siteB.com. Без такой же политики происхождения JavaScript, написанный авторами siteA.com, может заставить ваш браузер отправлять запросы на siteB.com, используя ваши файлы cookie аутентификации для siteB.com. Таким образом, siteA.com может украсть секретную информацию, которой вы делитесь с siteB.com.

Иногда вам нужно работать с кросс-доменом, в который входит CORS. CORS ослабляет ту же политику происхождения для domainA.com, используя Access-Control-Allow-Origin заголовок для перечисления других доменов (domainB.com), которым доверяют запуск JavaScript, который может взаимодействовать с domainA.com.

Чтобы понять, какой домен должен обслуживать заголовки CORS, подумайте об этом. Вы посещаете malware.com, который содержит JavaScript, который пытается сделать кросс-доменный запрос к mybank.com. Решение о том, устанавливает ли он заголовки CORS, ослабляют ли ту же политику происхождения, позволяющую JavaScript с вредоносного сайта взаимодействовать с ним, должен решать mybank.com, а не malware.com. Если бы malicous.com мог установить собственные заголовки CORS, разрешающие собственный доступ JavaScript к mybank.com, это полностью аннулировало бы ту же политику происхождения.

Я думаю, что причиной моей плохой интуиции является точка зрения, которую я имею при разработке сайта. Это мой сайт со всем моим JavaScript, поэтому он не делает ничего вредоносного, и я должен указать, с какими другими сайтами может взаимодействовать мой JavaScript. Когда на самом деле я должен думать, какие другие сайты JavaScript пытается взаимодействовать с моим сайтом, и должен ли я использовать CORS, чтобы разрешить их?

По моему собственному опыту, трудно найти простое объяснение, почему CORS вообще вызывает беспокойство.

Как только вы поймете, почему он там, заголовки и обсуждение станут намного понятнее. Я попробую в нескольких строках.


Все дело в файлах cookie. Файлы cookie хранятся на клиенте по его домену.

Пример истории: на вашем компьютере есть файл cookie для yourbank.com. Может быть, ваша сессия там.

Ключевой момент: когда клиент делает запрос к серверу, он отправляет файлы cookie, хранящиеся в домене, в котором находится клиент.

Вы вошли в свой браузер, чтобы yourbank.com. Вы просите показать все свои аккаунты. yourbank.com получает стопку файлов cookie и отправляет ответ (ваши учетные записи).

Если другой клиент отправляет серверу запрос из другого источника, эти файлы cookie отправляются, как и раньше. Рух-рох.

Вы просматриваете malicious.com. Вредоносный делает кучу запросов в разные банки, в том числеyourbank.com.

Поскольку файлы cookie проверяются должным образом, сервер авторизует ответ.

Эти куки собираются и отправляются - и теперь, malicious.com получил ответ от yourbank.

Ой.


Итак, теперь становятся очевидными несколько вопросов и ответов:

  • "Почему бы нам просто не заблокировать браузер от этого?" Ага. CORS.
  • "Как нам это обойти?" Попросите сервер сообщить запросу, что CORS в порядке.

Используя React и Axios, присоедините прокси-ссылку к URL и добавьте заголовок, как показано ниже

https://cors-anywhere.herokuapp.com/ + Your API URL

Просто добавив ссылку "Прокси", вы заработаете, но она также может снова выдать ошибку "Нет доступа". Следовательно, лучше добавить заголовок, как показано ниже.

axios.get(`https://cors-anywhere.herokuapp.com/[YOUR_API_URL]`,{headers: {'Access-Control-Allow-Origin': '*'}})
      .then(response => console.log(response:data);
  }

1. Клиент загружает код JavaScript MyCode.js из http://sitea/ - источник.

Код, который выполняет загрузку - ваш тег html-скрипта или xhr из javascript или чего-либо еще - поступил, скажем, с http://sitez/. И, когда браузер запрашивает MyCode.js, он отправляет заголовок Origin: "Origin: http://sitez/", потому что он может видеть, что вы запрашиваете siteA и siteZ!= SiteA. (Вы не можете остановиться или помешать этому.)

2. Заголовок ответа MyCode.js содержит Access-Control-Allow-Origin: http://siteb/, что, как я думал, означало, что MyCode.js было разрешено делать ссылки на сайт B.

нет. Это означает, что только siteB разрешено делать этот запрос. Таким образом, ваш запрос MyCode.js от siteZ получает ошибку, а браузер обычно ничего не дает. Но если вы заставите свой сервер вернуть ACAO: siteZ, вы получите MyCode.js . Или, если он отправит '*', это сработает, это впустит всех. Или если сервер всегда отправляет строку из заголовка Origin:... но... для безопасности, если вы боитесь хакеров ваш сервер должен разрешать только источники в шорт-листе, которым разрешено делать эти запросы.

Затем MyCode.js приходит с сайта A. Когда он отправляет запросы на сайт B, все они имеют перекрестное происхождение, браузер отправляет Origin: siteA, и siteB должен взять siteA, распознать его в коротком списке разрешенных запрашивающих и отправить обратно ACAO: siteA. Только тогда браузер позволит вашему сценарию получить результат этих запросов.

Я работаю с Express 4 и узлом 7.4 и угловой, у меня была та же проблема, мне помочь это:
а) сторона сервера: в файле app.js я даю заголовки для всех ответов, например:

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

это должно быть раньше всех роутеров.
Я видел много добавленных заголовков:

res.header("Access-Control-Allow-Headers","*");
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');

но мне это не нужно,
б) на стороне клиента: в send ajax вам нужно добавить: "withCredentials: true", например:

$http({
     method: 'POST',
     url: 'url, 
     withCredentials: true,
     data : {}
   }).then(function(response){
        // code  
   }, function (response) {
         // code 
   });

удачи.

Если вы используете PHP, попробуйте добавить следующий код в beaning файла php:

если вы используете localhost, попробуйте это:

header("Access-Control-Allow-Origin: *");

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

header("Access-Control-Allow-Origin: http://www.website.com");

Если вы хотите просто протестировать междоменное приложение, в котором браузер блокирует ваш запрос, вы можете просто открыть свой браузер в небезопасном режиме и протестировать свое приложение, не изменяя код и не делая ваш код небезопасным. Из MAC OS вы можете сделать это из терминальной линии:

open -a Google\ Chrome --args --disable-web-security --user-data-dir

В Python я использую Flask-CORS библиотека с большим успехом. Это делает работу с CORS супер простой и безболезненной. Я добавил код из документации библиотеки ниже.

Установка:

$ pip install -U flask-cors

Простой пример, который позволяет CORS для всех доменов на всех маршрутах:

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

@app.route("/")
def helloWorld():
  return "Hello, cross-origin-world!"

Для более конкретных примеров см. Документацию. Я использовал простой пример, приведенный выше, чтобы обойти проблему CORS в создаваемом ионном приложении, которое должно получить доступ к отдельному флеш-серверу.

Просто вставьте следующий код в ваш файл web.config.

Отметил, что вы должны вставить следующий код в <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>  

Я не могу настроить его на внутреннем сервере, но с этими расширениями в браузерах у меня работают:

Для Firefox: Cors Everywhere

Для Google Chrome: разрешить CORS: Access-Control-Allow-Origin

Примечание. CORS у меня работает с такой конфигурацией:

Для обмена между источниками установите заголовок: 'Access-Control-Allow-Origin':'*';

Php: header('Access-Control-Allow-Origin':'*');

Узел: app.use('Access-Control-Allow-Origin':'*');

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

Nginx и Appache

В дополнение к ответу апсиллера я хотел бы добавить вики-график, который показывает, когда запрос простой или нет (и предполетный запрос OPTIONS отправляется или нет)

Для простого запроса (например, хотлинкинга изображений) вам не нужно изменять файлы конфигурации сервера, но вы можете добавить заголовки в приложение (размещенное на сервере, например, в php), как упомянул Мелвин Герреро в своем ответе, - но помните: если вы добавите полный cors на вашем сервере (config), и в то же время вы разрешаете простые cors в приложении (например, php), это не будет работать вообще.

А вот конфигурации для двух популярных серверов.

  • включите CORS на Nginx (nginx.conf файл)

    location ~ ^/index\.php(/|$) {
       ...
        add_header 'Access-Control-Allow-Origin' "$http_origin" always; # if you change "$http_origin" to "*" you shoud get same result - allow all domain to CORS (but better change it to your particular domain)
        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';  # arbitrary methods
            add_header 'Access-Control-Allow-Headers' 'My-First-Header,My-Second-Header,Authorization,Content-Type,Accept,Origin'; # arbitrary headers
            add_header 'Content-Length' 0;
            add_header 'Content-Type' 'text/plain charset=UTF-8';
            return 204;
        }
    }

  • включите CORS в Appache (.htaccess файл)

    # ------------------------------------------------------------------------------
    # | Cross-domain Ajax requests                                                 |
    # ------------------------------------------------------------------------------
    
    # Enable cross-origin Ajax requests.
    # http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity
    # http://enable-cors.org/
    
    # change * (allow any domain) below to your domain
    Header set Access-Control-Allow-Origin "*"
    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"
    Header always set Access-Control-Allow-Credentials "true"

Заголовок ответа Access-Control-Allow-Origin указывает, может ли ответ использоваться совместно с запрашивающим кодом из данного источника.

Header type Response       header
Forbidden header name      no

Ответ, который говорит браузеру разрешить коду из любого источника обращаться к ресурсу, будет включать следующее:

Access-Control-Allow-Origin: *

Для получения дополнительной информации посетите здесь....

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

Access-Control-Allow-Origin: http://siteA.com

Я что-то добавляю в свою конфигурацию Amazon S3 CORS?

Или это то, что мне нужно как-то передать с моим запросом, т.е. реализовать в собственном коде?

В моем случае у меня есть несколько скриптов, которые помещены в корзину S3, но они не работают из-за разрешений:

скрипт по адресу 'https://*******-bucket.s3.amazonaws.com/debug_toolbar/js/toolbar.js?AWSAccessKeyId=AKIAVIMsfsdfsdVNIPN&Signature=jVtM4%2FfsehifheiuIEmmUdAfPXN от http: // Expires от http: // 25% localhost:8000'заблокирован политикой CORS: на запрошенном ресурсе отсутствует заголовок'Access-Control-Allow-Origin'.

И если мне нужно реализовать это в моем коде - как это сделать? Я работаю с Django, и оба скрипта мне не принадлежат. Я думаю, мне нужно настроить некоторые настройки в S3Boto3Storage, которые я использую для использования S3?

Для .NET Core 3.1 API с Angular

Startup.cs : добавить CORS

          //SERVICES
    public void ConfigureServices(IServiceCollection services){

        //CORS (Cross Origin Resource Sharing)
        //=====================================
        services.AddCors();
    }

    //MIDDLEWARES
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseRouting();

        //ORDER: CORS -> Authentication -> Authorization)
        //CORS (Cross Origin Resource Sharing)
        //=====================================  
        app.UseCors(x=>x.AllowAnyHeader().AllowAnyMethod().WithOrigins("http://localhost:4200"));

        app.UseHttpsRedirection();
    }
}

Контроллер : включить CORS для авторизованного контроллера

       //Authorize all methods inside this controller
 [Authorize]
 [EnableCors()]
 public class UsersController : ControllerBase
 {
    //ActionMethods
 }

Я использовал только расширение google chrome:Allow CORS: Access-Control-Allow-Origin

Рекомендуем посмотреть учебник

Кто не может контролировать бэкэнд для Options 405 Method Not Allowed.
Обходной путь для браузера Chrome.
выполнить в командной строке:
"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --disable-web-security --user-data-dir="path_to_profile"
Пример:
"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --disable-web-security --user-data-dir="C:\Users\vital\AppData\Local\Google\Chrome\User Data\Profile 2"

Большинство проблем с CORS возникают из-за того, что вы пытаетесь запросить через ajax на стороне клиента приложения react, angular, jquery, которые являются базовыми библиотеками внешнего интерфейса.

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

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

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