Обмен технологиями

Тщательное понимание междоменного интерфейса

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

 

Оглавление

1. Политика браузера в отношении одного и того же происхождения

1.1 Обзор политики одного и того же происхождения

1.2 Что такое происхождение?

2. Каковы ограничения на междоменные транзакции?

2.1 Ограничить доступ к DOM

2.2 Ограничить доступ к файлам cookie

2.3 Ограничить Ajax для получения данных

3 момента, на которые стоит обратить внимание

4CORS решает междоменные проблемы Ajax

4.1 Обзор CORS

4.2CORS решает простые междоменные запросы

4.3 Простые и сложные запросы

4.4CORS решает сложные междоменные запросы

4.5. Используйте библиотеку cors для быстрого завершения настройки.

5JSONP решает междоменные проблемы

6Настройте прокси для решения междоменных проблем

6.1 Настройте прокси-сервер самостоятельно

6.2 Используйте Nginx для создания прокси-сервера

6.3 Сборка сервера с помощью scaffolding


Адрес кода git clone https://gitee.com/childe-jia/cross-domain-test.git

1. Политика браузера в отношении одного и того же происхождения

1.1 Обзор политики одного и того же происхождения


Политика одного и того же происхождения — это политика, которой следуют браузеры для обеспечения безопасности ресурсов. Эта политика накладывает некоторые ограничения на доступ к ресурсам.
Описание политики одного и того же происхождения от W3C:Политика одинакового происхождения

1.2 Что такое происхождение?


1 исходные компоненты

изображение.png


2В таблице ниже только два источника в последней строке имеют одинаковое происхождение.

Источник 1

Источник 2

Это гомологично?

http://www.xyz.com/home

https://www.xyz.com/home

⛔Неоднородный️

http://www.xyz.com/home

http://mail.xyz.com/home

⛔Неоднородный

http://www.xyz.com:8080/home

http://www.xyz.com:8090/home

⛔Неоднородный

http://www.xyz.com:8080/home

http://www.xyz.com:8080/search

✅То же происхождение︎

 

3 запроса происхождения

изображение.png


4 Неоригинальный запрос

изображение.png


5 Краткое описание: Если «источник» не соответствует «целевому источнику», это означает «неисточник», также известный как «гетероисточник» или «междоменный».

2. Каковы ограничения на междоменные транзакции?


Например, если есть два источника: «Источник А» и «Источник Б», которые имеют «разное происхождение», то в браузере будут действовать следующие ограничения:

2.1 Ограничить доступ к DOM

Сценарий «Источника А» не может получить доступ к DOM «Источника Б».

  1. <!-- <iframe id="framePage" src="./demo.html"></iframe> -->
  2. <iframe id="framePage" src="https://www.baidu.com"></iframe>
  3. <script type="text/javascript" >
  4. function showDOM(){
  5. const framePage = document.getElementById('framePage')
  6. console.log(framePage.contentWindow.document) //同源的可以获取,非同源的无法获取
  7. }
  8. </script>

2.2 Ограничить доступ к файлам cookie

«Источник А» не может получить доступ к файлу cookie «Источника Б».

  1. <iframe id="baidu" src="http://www.baidu.com" width="500" height="300"></iframe>
  2. <script type="text/javascript" >
  3. // 访问的是当前源的cookie,并不是baidu的cookie
  4. console.log(document.cookie)
  5. </script>

2.3 Ограничить Ajax для получения данных

«Источник А» может отправлять запросы «Источнику Б», но не может получать данные ответа от «Источника Б».

  1. const url = 'https://www.toutiao.com/hot-event/hot-board/?origin=toutiao_pc'
  2. let result = await fetch(url)
  3. let data = await result.json();
  4. console.log(data)

Примечание. Среди вышеперечисленных ограничений наибольшее влияние оказывает ограничение браузера на сбор данных Ajax, которое часто встречается в реальной разработке.

3 момента, на которые стоит обратить внимание

  • 1Междоменные ограничения существуют только на стороне браузера, а на стороне сервера междоменные ограничения отсутствуют.
  • 2 Даже если он междоменный, Ajax-запросы могут выдаваться нормально, но данные ответа не передаются разработчику.
  • 3<link> , <script>、<img>...... 这些标签发出的请求也可能跨域,只不过浏览器对标签跨域不做严格限制,对开发几乎无影响

изображение.png

4CORS решает междоменные проблемы Ajax

4.1 Обзор CORS

Полное название CORS: Совместное использование ресурсов между источниками (Cross-Origin Resource Sharing) — это набор спецификаций, используемых для управления проверкой браузером междоменных запросов. Сервер следует спецификации CORS и добавляет специальные заголовки ответов для управления проверкой браузера. Общие правила заключаются в следующем:
●Сервер явно отклоняет междоменные запросы или не указывает это, и браузер не проходит проверку.
●Сервер четко указывает, что междоменные запросы разрешены, и проверка браузера проходит.
Примечание. Использование CORS для решения междоменных проблем является наиболее ортодоксальным способом и требует, чтобы сервер был «собственным».


4.2CORS решает простые междоменные запросы

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

изображение.png

Основной код на стороне сервера (в качестве примера возьмем экспресс-фреймворк):

  1. // 处理跨域中间件
  2. function corsMiddleWare(req,res,next){
  3. // 允许 http://127.0.0.1:5500 这个源发起跨域请求
  4. // res.setHeader('Access-Control-Allow-Origin','http://127.0.0.1:5500')
  5. // 允许所有源发起跨域请求
  6. res.setHeader('Access-Control-Allow-Origin','*')
  7. next()
  8. }
  9. // 配置路由并使用中间件
  10. app.get('/',corsMiddleWare,(req,res)=>{
  11. res.send('hello!')
  12. })

4.3 Простые и сложные запросы

CORS делит запросы на две категории: ① простые запросы и ② сложные запросы.

простой запрос

Сложный запрос

✅Метод запроса (метод): GET, HEAD, POST.

1 — это либо простой запрос, либо сложный запрос.
2 Сложные запросы автоматически отправляют предполетные запросы.

✅Поля заголовка запроса должны соответствовать«Спецификация безопасности CORS»
Краткое примечание: если заголовок запроса не изменяется вручную, он обычно соответствует этой спецификации.

✅Значение Content-Type заголовка запроса может быть только следующими тремя:
●текст/обычный
●multipart/form-data
●application/x-www-form-urlencoded

Что касается предполетных запросов:

  • 1Время отправки: предполетный запрос отправляется перед фактическим междоменным запросом и автоматически инициируется браузером.
  • 2 Основная функция: используется для подтверждения сервером разрешения следующего междоменного запроса.
  • 3Основной процесс: сначала инициируйте запрос OPTIONS. Если он прошел предварительную проверку, продолжайте инициировать фактический междоменный запрос.
  • 4 Содержимое заголовка запроса. Предварительный запрос OPTIONS обычно содержит следующие заголовки запроса:

Заголовок запроса

значение

Источник

Источник запроса

Метод запроса контроля доступа

Фактически запрошенный метод HTTP

Заголовки-запросов-контроля-доступа

Пользовательские заголовки, используемые в фактическом запросе (если есть)

4.4CORS решает сложные междоменные запросы

1 Шаг первый. Сервер сначала передает предварительный запрос браузера. Серверу необходимо вернуть следующий заголовок ответа:

заголовок ответа

значение

Доступ-Контроль-Разрешить-Происхождение

разрешенные источники

Методы-разрешения-контроля-доступа

разрешенные методы

Заголовки Access-Control-Allow

Разрешены пользовательские заголовки

Доступ-Контроль-Макс-Возраст

Время кэширования результатов предполетных запросов (необязательно)

изображение.png

2 Шаг 2. Обработка фактического междоменного запроса (так же, как вы обрабатываете простые междоменные запросы).

изображение.png

Основной код сервера:

  1. // 处理预检请求
  2. app.options('/students', (req, res) => {
  3. // 设置允许的跨域请求源
  4. res.setHeader('Access-Control-Allow-Origin', 'http://127.0.0.1:5500')
  5. // 设置允许的请求方法
  6. res.setHeader('Access-Control-Allow-Methods', 'GET')
  7. // 设置允许的请求头
  8. res.setHeader('Access-Control-Allow-Headers', 'school')
  9. // 设置预检请求的缓存时间(可选)
  10. res.setHeader('Access-Control-Max-Age', 7200)
  11. // 发送响应
  12. res.send()
  13. })
  14. // 处理实际请求
  15. app.get('/students', (req, res) => {
  16. // 设置允许的跨域请求源
  17. res.setHeader('Access-Control-Allow-Origin', 'http://127.0.0.1:5500')
  18. // 随便设置一个自定义响应头
  19. res.setHeader('abc',123)
  20. // 设置允许暴露给客户端的响应头
  21. res.setHeader('Access-Control-Expose-Headers', 'abc')
  22. // 打印请求日志
  23. console.log('有人请求/students了')
  24. // 发送响应数据
  25. res.send(students)
  26. })

4.5. Используйте библиотеку cors для быстрого завершения настройки.

В приведенной выше конфигурации вам необходимо настроить заголовок ответа самостоятельно или вручную инкапсулировать промежуточное программное обеспечение. С помощью библиотеки cors вы можете выполнить настройку более удобно.

●Установить корс

npm i cors

●Простая конфигурация

app.use(cors())

●Полная настройка cors

  1. // cors中间件配置
  2. const corsOptions = {
  3. origin: 'http://127.0.0.1:5500', // 允许的源
  4. methods: ['GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS'], // 允许的方法
  5. allowedHeaders: ['school'], // 允许的自定义头
  6. exposedHeaders: ['abc'], // 要暴露的响应头
  7. optionsSuccessStatus: 200 // 预检请求成功的状态码
  8. };
  9. app.use(cors(corsOptions)); // 使用cors中间件

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

5JSONP решает междоменные проблемы

1Обзор JSONP: JSONP использует<script>标签可以跨域加载脚本,且不受严格限制的特性,可以说是程序员智慧的结晶,早期一些浏览器不支持 CORS 的时,可以靠 JSONP 解决跨域。


2Основной процесс:

  • ○Шаг первый: клиент создает<script>标签,并将其src属性设置为包含跨域请求的 URL,同时准备一个回调函数,这个回调函数用于处理返回的数据。
  • ○Шаг 2. После получения запроса сервер инкапсулирует данные в функцию обратного вызова и возвращает их.
  • ○Шаг 3: вызывается функция обратного вызова клиента, и данные передаются в функцию обратного вызова в виде параметров.

3Иллюстрация:

изображение.png

4 примера кода:

  1. <button onclick="getTeachers()">获取数据</button>
  2. <script type="text/javascript" >
  3. function callback(data){
  4. console.log(data)
  5. }
  6. function getTeachers(url){
  7. // 创建script元素
  8. const script = document.createElement('script')
  9. // 指定script的src属性
  10. script.src= 'http://127.0.0.1:8081/teachers'
  11. // 将script元素添加到body中触发脚本加载
  12. document.body.appendChild(script)
  13. // script标签加载完毕后移除该标签
  14. script.onload = ()=>{
  15. script.remove()
  16. }
  17. }
  18. </script>

5jQuery, инкапсулированный jsonp

?callback=?' имеет фиксированный формат и будет автоматически анализироваться.

  1. $.getJSON('http://127.0.0.1:8081/teachers?callback=?',(data)=>{
  2. console.log(data)
  3. })

6Настройте прокси для решения междоменных проблем

6.1 Настройте прокси-сервер самостоятельно

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

  1. // 启动静态资源 让服务器跟页面同一个源
  2. app.use(express.static("./public"));

Настройте прокси с помощью http-proxy-middleware

  1. const { createProxyMiddleware } = require('http-proxy-middleware');
  2. app.use('/api',createProxyMiddleware({
  3. target:'https://www.toutiao.com',
  4. changeOrigin:true,
  5. pathRewrite:{
  6. '^/api':''
  7. }

 

преимущество:

  • Богатые функции: http-proxy-middleware предоставляет множество вариантов конфигурации для удовлетворения различных потребностей прокси.
  • Гибкая настройка нескольких прокси-серверов: можно настроить несколько прокси-серверов, соответствующих различным путям интерфейса.
  • Может перехватывать запросы. Запросы можно перехватывать и изменять с помощью пользовательских функций обработки.

недостаток:

  • Конфигурация относительно сложная: нужно понимать правила настройки и параметры библиотеки http-proxy-middleware.
  • Не подходит для производственных сред: http-proxy-middleware в основном используется в средах разработки и не подходит для производственных сред.

сцены, которые будут использоваться:

  • Подходит для интерфейсных проектов с использованием любого инструмента сборки и работает с любым сервером разработки.
  • Подходит для сценариев, когда необходимо гибко настроить несколько прокси-серверов.
  • Подходит для сценариев, когда запросы необходимо перехватывать и изменять.

6.2 Используйте Nginx для создания прокси-сервера

Общая идея: пусть nginx играет две роли: как сервера статического контента и как прокси-сервера.

Измените конфигурацию nginx следующим образом. Обратите внимание, что корневой каталог nginx предпочтительно не является диском C.

  1. # 配置nginx根目录
  2. location / {
  3. root D:dist;
  4. index index.html index.htm;
  5. }
  6. # 配置代理
  7. location /dev/ {
  8. # 设置代理目标
  9. proxy_pass http://sph-h5-api.atguigu.cn/;
  10. }

2. Измените внешний проект так, чтобы все запросы перенаправлялись в /dev, а затем переупаковывались.

  1. const request = axios.create({
  2. baseURL:'/dev',
  3. timeout:10000
  4. })

Затем напрямую получите доступ к серверу nginx. Например, если nginx работает на порту 8099, получите доступ.

http://localhost:8099

Тогда вы столкнетесь с проблемой обновления 404, добавьте конфигурацию nginx, чтобы решить ее.

  1. # 配置nginx根目录
  2. location / {
  3. root D:dist;
  4. index index.html index.htm;
  5. try_files $uri $uri/ /index.html; # 解决刷新404
  6. }
  7. # 配置代理
  8. location /dev/ {
  9. # 设置代理目标
  10. proxy_pass http://sph-h5-api.atguigu.cn/;
  11. }

Добавление этих двух "/" исключает dev.

6.3 Сборка сервера с помощью scaffolding

1. Используйте файл vue.config.js для настройки прокси:

Создайте файл vue.config.js в корневом каталоге проекта Vue и добавьте следующий код:

  1. module.exports = {
  2. devServer: {
  3. proxy: {
  4. '/api': {
  5. target: 'http://api.example.com',
  6. changeOrigin: true,
  7. pathRewrite: {
  8. '^/api': ''
  9. }
  10. }
  11. }
  12. }
  13. }

В приведенном выше коде мы используемdevServer Элементы конфигурации для настройки прокси-сервера.вproxyСвойства используются для настройки правил прокси,/apiУказывает путь к интерфейсу, требующему проксирования.targetАтрибут представляет адрес целевого сервера прокси-сервера.changeOriginАтрибут указывает, следует ли изменить адрес источника запроса.pathRewriteСвойство, используемое для переопределения запрошенного пути.

преимущество:

  • Простая настройка: используя конфигурацию прокси-сервера webpack-dev-server, вам нужно всего лишь выполнить простую настройку в файле конфигурации веб-пакета.
  • Комплексная функциональность: webpack-dev-server предоставляет множество вариантов конфигурации для удовлетворения большинства потребностей прокси.
  • Может перехватывать запросы. Запросы можно перехватывать и изменять с помощью пользовательских функций обработки.

недостаток:

  • Сервер необходимо перезапустить: после изменения конфигурации необходимо перезапустить webpack-dev-server, чтобы изменения вступили в силу.
  • Не подходит для производственных сред: webpack-dev-server в основном используется в средах разработки и не подходит для производственных сред.

сцены, которые будут использоваться:

  • Он подходит для интерфейсных проектов, созданных с использованием webpack и запуска сервера разработки через webpack-dev-server.
  • Он подходит для сценариев, требующих простой настройки прокси-сервера и не требующих частого изменения конфигурации прокси-сервера.