предисловие
CORSв настоящее время в дополнение кjsonpCORSXMLHttpRequestrequest, тем самым преодолевая ограничение, согласно которому AJAX может использоваться только из одного и того же источника.
будет использовать толькоCORSНам этого междоменного подхода недостаточно. Нам нужно знать, что есть, и больше о том, почему. Ошибка заключается в следующем:
использоватьfetchОшибка запроса следующая:
что такое кросс домен
объяснениеCORSПрежде чем нам нужно понять, что такое кросс-домен. Краеугольным камнем безопасности браузера является «политика того же происхождения». «Гомологичный» означает «три одинаковых»:
- тот же протокол
- такое же доменное имя
- тот же порт
Пример:http://www.example.com
http://www.example.com/a.html 同源
http://example.com 域名不同(不同源)
http://www.example.com:8081 端口不同(默认80)
https://www.example.com 协议不同(不同源)
Цель политики единого источника — обеспечить безопасность пользовательской информации и предотвратить кражу данных вредоносными веб-сайтами.
Ограничения: если он негомологичен, ограничено всего три поведения.
-
Cookie,LocalStorage,IndexDBНевозможно прочитать. -
DOMне может получить. AJAX
CORS принцип аналитического
CORSимеет перекрестное происхождениеAJAXJSONPтолько отправитьGETпросьба, ноCORSДопускаются любые запросы.
весьCORSПроцесс связи завершен автоматически браузером и не требует участия пользователя. Для разработчиков,CORSОбщение и гомологияAJAXРазницы в общении нет, код точно такой же.Как только браузер обнаружит, что запрос AJAX является перекрестным, он автоматически добавит некоторую дополнительную информацию в заголовок, а иногда будет дополнительный запрос, но пользователь этого не почувствует.. Поэтому осознайтеCORSКлючом к общению являетсясервер. Пока сервер реализуетCORSИнтерфейс, вы можете общаться через истоки.
Один или два запроса
Браузеры делят запросы CORS на две категории: простые запросы и не очень простые запросы. Пока следующие два условия выполняются одновременно, это простой запрос.
(1) Метод запроса является одним из следующих трех методов:
HEAD
GET
POST
(2) Информация заголовка HTTP Заголовки запроса не превышают следующих полей:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
Если два вышеуказанных условия не выполняются одновременно, это непростая заявка.
- Основной процесс
CORSпросить. В частности, в первую информацию добавить одинOriginполе.
Ниже приведен пример, когда браузер обнаружил это перекрестное происхождение.AJAXЗапрос является простым запросом, и он автоматически добавляется к информации заголовка.Originполе.
GET /cors HTTP/1.1
Origin: http://api.bob.com
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...
Как показано: (ДобавленоOriginполе)В приведенной выше информации заголовка,
OriginПоле используется для указания источника (протокол + доменное имя + порт), из которого пришел этот запрос. На основе этого значения сервер решает, соглашаться ли на запрос.
еслиOriginУказанный источник не входит в сферу действия лицензии, сервер вернет обычныйHTTPреагировать. Браузер обнаружил, что информация заголовка этого ответа не содержитAccess-Control-Allow-Originполе (подробнее см. ниже), вы знаете, что что-то пошло не так, и выдается ошибка, называемаяXMLHttpRequestизonerrorЗахват функции обратного вызова. Обратите внимание, что этот тип ошибки не может быть идентифицирован по коду состояния, потому чтоHTTPКод состояния ответа может быть200.
еслиOriginЕсли указанное доменное имя находится в допустимом диапазоне, ответ, возвращаемый сервером, будет содержать несколько дополнительных полей заголовка.
Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: FooBar
Content-Type: text/html; charset=utf-8
В приведенной выше информации заголовка есть три поля, относящиеся к запросам CORS, все из которых начинаются сAccess-Control-начало.
(1)Access-Control-Allow-OriginЭто поле обязательно к заполнению.它的值要么是请求时OriginЗначение поля, либо*Указание запроса на принятие любого доменного имени.
(2)Access-Control-Allow-CredentialsЭто поле является необязательным.它的值是一个布尔值,表示是否允许发送Cookie. по умолчанию,CookieНе включен вCORS请求之中。 установить какtrueЭто означает, что сервер явное разрешение,CookieМожно включить в запрос и отправить на сервер вместе. Это значение также может быть установлено только наtrue, если сервер не хочет, чтобы браузер отправлялCookieПросто удалите это поле.В случае кроссдоменности нужно настроить не только внешний интерфейсwithCredentials, бэкэнд тоже нужно настроитьAccess-Control-Allow-Credentialsиз. По запросуResponse Headersвидел вAccess-Control-Allow-Credentials: true
(3)Access-Control-Expose-HeadersЭто поле является необязательным.CORSпри запросе,XMLHttpRequestобъектgetResponseHeader()Метод может получить только 6 основных полей:Cache-Control,Content-Language,Content-Type,Expires,Last-Modified,Pragma. Если вы хотите получить другие поля, вы должныAccess-Control-Expose-Headersуказано внутри. Приведенный выше пример указывает это,getResponseHeader('FooBar')Может вернутьFooBarзначение поля.
2,withCredentialsАтрибуты
Как указано выше,CORSпроситьНе отправляется по умолчаниюCookieа такжеHTTPИнформация о сертификации. Если хочешьCookieОтправить его на сервер, с одной стороны сервер должен согласовать, указатьAccess-Control-Allow-Credentialsполе.
Access-Control-Allow-Credentials: true
С другой стороны, разработчики должныAJAXоткрыть по запросуwithCredentialsАтрибуты.
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
В противном случае, даже если сервер согласится отправитьCookieБраузер не будет отправлен. Альтернативно, сервер требует настройкиCookie, браузер тоже не справится.
Однако если опуститьwithCredentialsНастройки, некоторые браузеры все равно отправят его вместеCookie. В этом случае вы можете явно закрытьwithCredentials.
xhr.withCredentials = false;
Следует отметить, что если вы хотите отправитьCookie,Access-Control-Allow-OriginОн не может быть установлен в виде звездочки, и необходимо указать явное доменное имя, соответствующее запрошенной странице. в то же время,CookieПолитика того же происхождения по-прежнему соблюдается, только те, которые установлены с доменным именем сервера.Cookieбудут загружены, другие доменные именаCookieне будут загружены, и (кросс-происхождение) в исходном коде страницыdocument.cookieНе могу прочитать доменное имя сервераCookie.
redentials(用户凭证): Значение Cookie, HTTP-аутентификация и клиентские сертификаты TLS не включают в себя прокси-аутентификацию или заголовки источника. Значение по умолчанию является ложным, устанавливая гомологичный ресурсwithCredentialsНет эффекта.
3. Непростой запрос
- предварительный запрос
Этот браузер отправляетдваждыhttpпросить. первый разRequest Method: OPTIONS, и запросите нужный контент во второй раз.
Запрос является непростым, что есть запрос к серверу с особыми требованиями, например, запросPUTилиDELETE,илиContent-TypeТип поляapplication/json.
не простой запросCORSЗапросы будут добавлены один раз перед официальным общениемHTTPзапрос запроса, называемыйпредварительный запрос (preflight).
Распространенные ошибки следующие:
Это означает, что предварительный запрос не проходит, и формальный запрос больше не выдается., когда был сделан предварительный запрос, он не был найден
tokenэто поле, поэтому предварительный запрос не выполняется. На этом этапе его необходимо настроить на стороне сервера.optionsзапрос вернулся. Например:response.setHeader("Access-Control-Allow-Headers", "Content-Type,Access-Token,Token").so Запрос прелета правильный.HEADER содержит настраиваемые поля, и браузер сначала отправит запрос Options.Если запрос проходит, официальный POST-запрос продолжается, а если он не пройден, он возвращает указанную выше ошибку.
Браузер сначала запрашивает у сервера, где находится домен текущей веб-страницы, находится ли он в списке серверов лицензий и какой из них можно использовать.HTTPXMLHttpRequest
Request MethodдляOPTIONS, как показано на рисунке:Ниже приведен сценарий JavaScript для браузера.
var url = 'http://api.alice.com/cors';
var xhr = new XMLHttpRequest();
xhr.open('PUT', url, true);
xhr.setRequestHeader('X-Custom-Header', 'value');
xhr.send();
В приведенном выше кодеHTTPМетод запросаPUTи отправить собственный заголовокX-Custom-Header.
Браузер обнаруживает, что это непростой запрос, и автоматически выдает «предварительный» запрос, запрашивая у сервера подтверждение того, что его можно запросить. Вот как выглядит этот «предполетный» запросHTTPинформация заголовка.
OPTIONS /cors HTTP/1.1
Origin: http://api.bob.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...
Метод запроса, используемый для «предварительных» запросов:OPTIONSУказывает на то, что запрос используется для запроса. В информации заголовка ключевым полем являетсяOrigin, который представляет собой запрос от источника.
КромеOriginполе, информация заголовка «предпечатного» запроса включает два специальных поля.
(1)Access-Control-Request-MethodЭто поле необходимо для перечисления браузераCORSЧто будет использовать запросHTTPметод, приведенный выше примерPUT.
(2)Access-Control-Request-Headers
Поле представляет собой строку, разделенную запятыми, указывающую браузерCORSПоля заголовка, которые запрос будет отправлять дополнительно, приведенный выше примерX-Custom-Header.
- Ответ на предварительный запрос
Origin,Access-Control-Request-Methodа такжеAccess-Control-Request-HeadersПосле подтверждения того, что запросы из разных источников разрешены, вы можете ответить.
HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain
надHTTPВ ответ ключAccess-Control-Allow-Originполе, указывающееhttp://api.bob.comДанные можно запросить. В этом поле также можно установить звездочку, чтобы указать согласие на любой запрос из другого источника.
Access-Control-Allow-Origin: *
Если браузер отклоняет запрос «предпечатной проверки», он возвращает обычныйHTTPответ, но ничегоCORSСвязанные поля заголовка. В этот момент браузер решит, что сервер не согласен с предварительным запросом, и, таким образом, вызовет ошибку, которая вызываетсяXMLHttpRequestобъектonerrorЗахват функции обратного вызова. Консоль распечатает следующую информацию об ошибке.
XMLHttpRequest cannot load http://api.alice.com.
Origin http://api.bob.com is not allowed by Access-Control-Allow-Origin.
Другие ответы от сервераCORSСоответствующие поля следующие.
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 1728000
(1)Access-Control-Allow-MethodsЭто поле является обязательным, и его значение представляет собой строку с разделителями-запятыми, указывающую все методы, поддерживаемые сервером для междоменных запросов. Обратите внимание, что возвращаются все поддерживаемые методы, а не только запрошенный браузером. Это сделано для того, чтобы избежать множественных "предполетных" запросов.
(2)Access-Control-Allow-HeadersЕсли запрос браузера включаетAccess-Control-Request-Headersполе, тоAccess-Control-Allow-HeadersПоле, обязательное для заполнения. Это также строка с разделителями-запятыми, указывающая все поля заголовка, поддерживаемые сервером, не ограничиваясь теми, которые запрошены браузером в «предпечатной проверке».
(3)Access-Control-Allow-Credentials
Это поле имеет то же значение, что и для простого запроса.
(4)Access-Control-Max-Age
Это поле является необязательным и используется для указания периода действия этого запроса предварительной проверки в секундах. В приведенном выше результате период действия составляет 20 дней (1 728 000 секунд), что означает, что ответ разрешено кэшировать в течение 1 728 000 секунд (то есть 20 дней). В течение этого периода нет необходимости выдавать еще один предварительный запрос. .
- Обычный запрос и ответ браузеру
После того, как сервер через «предполетный» запрос, после каждого обычного браузераCORSЕсли вы спросите, у вас будет простая просьба.Originполе заголовка. Ответ сервера также будет иметьAccess-Control-Allow-Originполе заголовка.
Ниже приведен обычный браузер после запроса «preflight».CORSпросить.
PUT /cors HTTP/1.1
Origin: http://api.bob.com
Host: api.alice.com
X-Custom-Header: value
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...
OriginПоля добавляются браузером автоматически.
Ниже приведен нормальный ответ сервера.
Access-Control-Allow-Origin: http://api.bob.com
Content-Type: text/html; charset=utf-8
В приведенной выше информации заголовка,Access-Control-Allow-OriginПоля являются обязательными для каждого ответа.
Флаг XMLHTTPREQUEST INCREDENTIESS установлен на TRUE, что при этом файлы cookie отправлены на сервер. Поскольку это простой запрос GET, браузер не запустит его «предварительный запрос». Тем не менее, если ответ не несет ответ на сервере доступа-контроль - учетные данные: True, браузер не будет возвращать содержимое ответа на запрашивающий отправитель.
Для запросов с учетными данными сервер НЕ ДОЛЖЕН устанавливать для Access-Control-Allow-Origin значение «*». Это связано с тем, что информация о файлах cookie передается в заголовке запроса.Если значение Access-Control-Allow-Origin равно «*», запрос завершится ошибкой. при установке значения Access-Control-Allow-Origin вfoo.example запрос будет выполнен успешно. Если установлено значение *, будет сообщено о следующей ошибке:
- Когда браузер отправитпростой запрос? При каких обстоятельствах браузер будет отправлятьне простой запросШерстяная ткань?
Стандарт Cross-Origin Resource Sharing добавляет новый набор полей заголовка HTTP, которые позволяют серверам объявлять, какие исходные сайты имеют разрешение на доступ к каким ресурсам через браузер. Кроме того, спецификация требует,Для методов HTTP-запроса, которые могут иметь побочные эффекты для данных сервера (особенно HTTP-запросы, отличные от GET, или POST-запросы в сочетании с определенными типами MIME), браузер должен сначала инициировать предварительный запрос с использованием метода OPTIONS, тем самым получая, позволяет ли сервер междоменный запрос. После того, как сервер подтвердит разрешение, инициируется фактический HTTP-запрос. В ответе на предварительный запрос сервер также может уведомить клиента о том, нужно ли ему передавать учетные данные (включая файлы cookie и данные, связанные с аутентификацией HTTP).
Некоторые запросы не вызывают CorsПредварительный запрос. Если запрос удовлетворяет все следующие условия, запрос может считаться «простым запросом»:
GET
HEAD
POST
два,FetchCORS安全的首部字段集合,不得人为设置该集合之外的其他首部字段。 Коллекция:
Accept
Accept-Language
Content-Language
Content-Type (需要注意额外的限制)
DPR
Downlink
Save-Data
Viewport-Width
Width
три,Content-TypeЗначение ограничено одним из следующих трех:
text/plain
multipart/form-data
application/x-www-form-urlencoded
И на изображении ниже, потому чтоRequest HeaderсодержитAccess-Control-Request-Headers: token, искусственно заданное радикальное поле. таким образом вызываяпредварительный запрос.
Сравнение с JSONP
CORSа такжеJSONPиспользуется для тех же целей, но менееJSONPБолее могущественный.
JSONPтолько поддержкаGETпросить,CORSПоддержка всех типовHTTPпросить.JSONPПреимущество в том, что он поддерживает старые браузеры и можетCORSсайт запрашивает данные.
демонстрация кода
В случае перекрестного доменного запроса консоль браузера сообщит о следующей ошибке:
На этом этапе вам нужно установить его на стороне сервера (например, nodejs)
const http = require('http')
http.createServer(function (request, response) {
console.log('request come', request.url)
response.writeHead(200, {
'Access-Control-Allow-Origin': '*'
})
response.end('123')
}).listen(8080)
Возврат следующим образом:
Вы можете видеть, что междоменный запрос был успешно принят.
Основные моменты:
В самом деле, независимо от того, установили ли мы Access-Control-Allow-Origin: *, Браузер отправит запрос на наш сервер и получит возвращенный контент. Когда браузер анализирует найденныйResponse HeadersНет в Access-Control-Allow-Origin: *.
ноAccess-Control-Allow-Origin: *Этот параметр явно небезопасен, потому что он эквивалентен разрешению доступа ко всем доменным именам, поэтому мы также можем установить для доступа конкретное доменное имя. Например:Access-Control-Allow-Origin: http://www.baidu.comТаким образом, только вhttp://www.baidu.comПри доступе к доменному имени браузер может разрешить его обычным образом..
Суммировать
Междоменная проблема — это проблема, с которой столкнется каждый разработчик интерфейса, и существуют не только способы междоменногоJsonp,CORS,а такжеpostMessage,webScorketДругими словами, когда мы сталкиваемся с междоменными проблемами, мы можем быстро найти проблему и узнать причину ее возникновения, что является необходимым качеством для каждого нашего программиста. Надеюсь, эта статья поможет вам.
Ссылаться на:HTTP-контроль доступа (CORS) Headers
приложение:
Добро пожаловать в группу и развивайтесь вместе!
Если QR-код недействителен, вы можете отсканировать код и добавить свой личный WeChat: Note Nuggets FE, который перетянет вас в группу.