Веб-разработчики бэкенда редко полностью понимают проблемы кросс-начала, потому что они редко имеют дело с 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один из способов; - Заголовок имеет только следующие поля:
AcceptAccept-LanguageContent-Language-
Content-Typeявляется одним из следующих трех:- text / plain`
multipart / form-dataapplication / x-www.form-urlencoded
DPRDownloadlinkSave-DataViewport-WidthWidth
- любой в запросе
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-urlencodedmultipart/form-datatext/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]