Веб-разработчики бэкенда редко полностью понимают проблемы кросс-начала, потому что они редко имеют дело с JavaScript. Но как веб-разработчик, знание междоменных запросов и способов решения междоменных проблем может сделать общение с разработчиками внешнего интерфейса более плавным.
В этой статье будут представлены некоторые концепции, связанные с междоменными запросами, и способы решения проблемы междоменных запросов браузера в серверной части (Python).
1. Что такое междоменный запрос
Во-первых, нам нужно понять, что такое кросс-оригинальный запрос. Проще говоря, когда ресурс сервера запрашивает ресурс с другого сервера (с другим доменным именем или портом), инициируется междоменный HTTP-запрос.
В качестве простого примераhttp://example-a.com/index.html
Эта HTML-страница запрашиваетhttp://example-b.com/resource/image.jpg
Когда этот ресурс изображения (инициирующий запрос Ajax, а не<img>
тег), должен инициировать междоменный запрос.
Без какой-либо обработки этот междоменный запрос не может быть успешно запрошен, поскольку браузер основан наТа же политика происхожденияБудут определенные ограничения на междоменные запросы.
2. Политика одинакового происхождения браузера
Это ведет кБраузерная политика того же происхождения (Same-origin policy), политика того же источника ограничивает взаимодействие документов или сценариев, загруженных из одного источника, с ресурсами из другого источника. Это важный механизм безопасности для изоляции потенциально вредоносных файлов.
Что такое гомология? Гомологичность должна соответствовать трем условиям одновременно:
- Запрашиваемый протокол одинаковы (например, тот же протокол HTTP)
- Запрошенное доменное имя совпадает (например,
www.example.com
) - Запрошенный порт тот же (например, тот же порт 80)
Второй момент, на который стоит обратить внимание, это то, что доменное имя должно быть точно таким же, напримерblog.example.com
иmail.example.com
Эти два домена, хотя их домены верхнего и второго уровня (обаexample.com
) одинаковы, но доменное имя третьего уровня (blog
иmail
) не совпадают, поэтому их нельзя считать одним и тем же доменным именем.
Если три вышеуказанных условия не выполняются одновременно, это не соответствует политике браузера в отношении одного и того же происхождения.
Исправлятьdocument.domain
Параметры могут изменить текущий источник, например.blog.example.com
хотите получить доступ к родительскому доменуexample.com
, вы можете выполнить следующий сценарий JavaScript, чтобы изменить его:
|
|
ноdocument.domain
не может быть установлено наfoo.com
илиbar.com
, потому что они неblog.example.com
супер домен.
Конечно, не все взаимодействия будут перехватываться политикой одного и того же источника. Следующие два взаимодействия не будут запускать политику одного и того же источника:
- Записи между источниками, такие как гиперссылки, перенаправления и отправка форм, требуют предварительной проверки нескольких HTTP-запросов;
- Встраивание разных источников:
-
<script>
Тег встроенный кросс-домен сценариев; -
<link>
CSS-файл, в который встроен тег; -
<img>
Пометить встроенное изображение; -
<video>
и<audio>
Теги встраиваются в мультимедийные ресурсы; -
<object>
,<embed>
,<applet>
плагин; -
@font-face
Внедрение шрифта, некоторые браузеры позволяют междоменные шрифты (перекрестные шрифты), шрифты, которые требуют гомологичных (шрифты одинакового происхождения); -
<frame>
и<iframe>
Любой загруженный ресурс, который может использовать сайтX-Frame-Options
заголовки сообщений для организации этой формы междоменного взаимодействия.
-
Что делать, если в браузере отсутствует механизм безопасности политики того же источника? Представьте, когда вы входите в системуwww.bank.com
Когда веб-сайт банка работает, браузер сохраняет информацию о файлах cookie при входе в систему. Если политика того же источника отсутствует, при посещении других веб-сайтов другие веб-сайты могут считывать информацию о файлах cookie, срок действия которых еще не истек, чтобы подделать операцию входа в систему. и привести к материальному ущербу.
3. CORS (междоменное совместное использование ресурсов, междоменное совместное использование ресурсов)
Хотя политика одного и того же источника в определенной степени обеспечивает безопасность, что, если это обычный запрос, который должен быть междоменным?
Существует четыре распространенных метода:
- JSONP
-
<iframe>
Этикетка - CORS (совместное использование ресурсов из разных источников, совместное использование ресурсов из разных источников)
- прокси-сервер
Первые два метода по существу используют уязвимость политики одного и того же источника браузера для выполнения междоменных запросов. Они не являются рекомендуемыми практиками и могут использоваться только в качестве задержки в браузерах более ранних версий.
Подход прокси-сервера заключается в том, чтобы позволить браузеру получить доступ к серверу того же источника, а затем серверу того же источника для доступа к целевому серверу.Хотя проблемы междоменных запросов можно избежать, запрос, который изначально требовался только один раз запрашивается дважды, что несомненно увеличивает затраты времени.
Текущий основной метод заключается в использовании CORS, который также является основным содержанием ниже.
3.1 Что такое КОРС
CORS на самом деле является спецификацией, сформулированной браузерами. Его реализация в основном на стороне сервера. Он ограничивает доступные домены через некоторые заголовки HTTP. Например, страница A должна получить доступ к данным на сервере B. Если сервер B объявляет, что A разрешен домен доступ по имени, то междоменный запрос от A к B может быть выполнен.
Для HTTP-запросов, которые имеют побочные эффекты для данных сервера, браузер используетOPTIONS
Метод инициирует предварительный запрос, чтобы вы могли узнать, разрешает ли сервер междоменный запрос.После того, как сервер подтвердит разрешение, будет инициирован фактический запрос. В ответе на предварительный запрос сервер также может сообщить клиенту, требуется ли аутентификационная информация.
3.2 Простые запросы
Некоторые запросы не запускают предварительные запросы CORS, мы называем такие запросы простыми запросами.
Запрос может считаться простым запросом, если он соответствует всем следующим условиям:
-
GET
,HEAD
,POST
один из способов; - Заголовок имеет только следующие поля:
Accept
Accept-Language
Content-Language
-
Content-Type
является одним из следующих трех:- text / plain`
multipart / form-data
application / x-www.form-urlencoded
DPR
Downloadlink
Save-Data
Viewport-Width
Width
- любой в запросе
XMLHttpRequestUpload
Ни один из объектов не зарегистрировал прослушивателей событий,XMLHttpRequestUpload
объект может использоватьXMLHttpRequest.upload
доступ к собственности; - не используется в запросе
ReadableStream
объект.
например1, например сайтhttp://foo.example
веб-приложений хотят получить доступhttp://bar.other
Ресурсы,http://foo.example
Веб-страницы могут содержать код JavaScript, аналогичный следующему:
|
|
Студенты, знакомые с JavaScript, могут найти этот код дляhttp://bar.other/resources/public-data/
инициировалGET
Сообщения запроса, запроса и ответа следующие.
Сообщение запроса:
Ответное сообщение:
В сообщении запросаOrigin
поле указывает, что запрос исходит отhttp://foo.example
.
В ответном сообщении,Access-Control-Allow-Origin
поле установлено на*
, что указывает на то, что к ресурсу может получить доступ любой домен.
использоватьOrigin
иAccess-Control-Allow-Origin
Можно выполнить простейший контроль доступа. Если сервер разрешает толькоhttp://foo.example
Доступ к домену должен быть установлен следующим образом:
|
|
3.3 Предполетный запрос
В отличие от простых запросов, сначала необходимо использовать требования «запросы с предварительной проверкой».OPTIONS
Этот метод отправляет на сервер предварительный запрос, чтобы узнать, разрешает ли сервер запрос или ему необходимо передавать информацию аутентификации. Использование «предварительного запроса» может предотвратить неожиданное влияние междоменных запросов на пользовательские данные сервера.
Если запрос соответствует всем следующим условиям, сначала необходимо отправить предварительный запрос.
- Был использован любой из следующих методов HTTP:
PUT
,DELETE
,CONNECT
,OPTIONS
,TRACE
,PATCH
; - Остальные поля, кроме поля Заголовок простого запроса, задаются в Заголовке (см. описание поля Заголовок в простом запросе);
-
Content-Type
Значение не является одним из следующих:application/x-www-form-urlencoded
multipart/form-data
text/plain
- Запрошено
XMLHttpRequestUpload
Объект имеет любое количество зарегистрированных прослушивателей событий; - используется в запросе
ReadableStream
объект.
Например следующий пример1:
|
|
Приведенный выше код отправляет документ XML с помощью запроса POST, который включает настраиваемое поле заголовка.X-PINGOTHER: pingpong
. Кроме того, запрошенныйContent-Type
заapplication/xml
, поэтому запрос должен сначала инициировать «запрос предварительной проверки».
Сообщение запроса OPTIONS:
Ответное сообщение OPTIONS:
Метод OPTIONS — это метод, определенный в HTTP/1.1 для получения дополнительной информации с сервера, и этот метод не влияет на ресурсы сервера. Заголовки предварительного запроса содержат два поля:
|
|
Access-Control-Request-Method: POST
поле сообщает серверу, что фактический запрос будет использоватьPOST
метод;Access-Control-Request-Headers
Поля сообщают серверу, что фактический запрос будет содержать два настраиваемых поля заголовка запроса:X-PINGOTHER
иContent-Type
, на основании которых сервер решает, разрешен ли фактический запрос.
Ответное сообщение OPTIONS указывает, что сервер будет принимать последующие фактические запросы, где:
|
|
-
Access-Control-Allow-Origin
прямое разрешениеhttp://foo.example
домен для доступа; -
Access-Control-Allow-Methods
Указывает, что клиенту разрешено отправлятьPOST
,GET
,OPTIONS
просить; -
Access-Control-Allow-Headers
Указывает, что клиент порядка слов несетX-PINGOTHER
иContent-Type
Поле заголовка; -
Access-Control-Max-Age
Указывает, что ответ действителен в течение 86 400 секунд (24 часа). В течение этого времени браузеру не нужно повторно инициировать предварительный запрос для того же запроса. (Обратите внимание, что сам браузер поддерживает максимальное время действия, если поле заголовка превышает максимальное время действия, оно не вступит в силу).
После того, как предварительный запрос завершен, фактический запрос отправляется, и сообщение запроса выглядит следующим образом:
|
|
Ответное сообщение:
|
|
3.4 Запросы с аутентификацией
В общем, для междоменногоXMLHTTPRequest
илиFetch
Запрос, браузер не будет отправлять учетные данные удостоверения личности, если вам нужно отправить учетные данные удостоверения личности, вам нужно отправитьXMLHTTPRequest
изwithCredentials
свойство установлено наtrue
.
Например1, следующий код представляетhttp://foo.example
В направленииhttp://bar.other
ОтправитьGET
запросить и установитьCookies
.
|
|
поставивwithCredentials
Установить какtrue
тем самым посылаюCookies
запрос. Потому что это простойGET
запрос, поэтому браузер не будет инициировать предварительный запрос, однако, если ответ сервера не содержитAccess-Control-Allow-Credentials: true
, браузер не вернет содержимое ответа отправителю запроса.
Для запросов с аутентификацией сервер не должен устанавливатьAccess-Control-Allow-Origin
значение*
.
3.5 Заголовки для CORS
Ниже перечислены все поля заголовка, используемые в HTTP-запросах и ответах.Связанная документация.
Заголовки HTTP-запроса:
-
Origin
: указывает исходный сайт предварительного запроса или фактического запроса, он не содержит никакой информации о пути, только имя сервера (URI); -
Access-Control-Request-Method
: используется для предварительных запросов, функция заключается в том, чтобы сообщить серверу метод HTTP, используемый фактическим запросом; -
Access-Control-Request-Headers
: используется для предварительных запросов, функция состоит в том, чтобы сообщить серверу поле заголовка, используемое фактическим запросом;
Заголовки ответа HTTP:
-
Access-Control-Allow-Origin
: указывает URI внешнего домена, которому разрешен доступ к ресурсу; -
Access-Control-Expose-Headers
: разрешить серверу внести в белый список заголовки, к которым разрешен доступ браузеру, чтобы браузер мог использоватьgetResponseHeader
способ доступа; -
Access-Control-Max-Age
: указывает, как долго результат предварительного запроса может кэшироваться; -
Access-Control-Allow-Credentials
: указывает, когда браузерcredentials
Разрешить ли браузер для чтения содержимого ответа при установке true; -
Access-Control-Allow-Headers
: ответ на предварительные запросы. Он определяет поля заголовка, которые разрешено использовать в фактическом запросе.
4. Серверная реализация
Для реализации CORS необходимо провести некоторую работу на стороне сервера, главное добавить указанные поля в заголовок ответа.
Если вы используете разработку Python + Flask, вы можете перейти кafter_app_request
Добавьте указанный заголовок ответа в функцию ловушки:
|
|
Другие языки можно обрабатывать в соответствующей функции хука.
использованная литература
- Cross-Origin Resource Sharing (CORS)
- Same-origin policy
- Политика одинакового происхождения в браузере и как ее избежать
- Источник для этого примера:Cross-Origin Resource Sharing (CORS) [return]