предисловие
Годы назад Quit после сезона готов начать видеть передний конец соответствующих знаний от содержания интервью, стремится исследовать серию знаний, углублен в сфере компетенции. Сосредоточение внимания на практике и подготовка к первичным интерфейсным интервью студентов, например, прикрепить фактический код и связанные с ними вопросы - имя семейства на переднем конце интервью с [сломанным] лысым - потому что каждый консенсус круг, технология и развитие пропорционально сумме. 😄 надеюсь, что вы все скоролысыйПреодолейте узкое место~
Слишком много статей о вопросах собеседования или определенной точке знаний.Вот хочу просто записать свое личное резюме в виде репозитория кода и вывести статью.Ведь теория не то же самое, что практика, и если вы знаете что это такое, вы должны знать, почему. Только тогда мы сможем по-настоящему понять~
Связанные серии статей того же типа:
- Интервью с Лысым По — HTTP и HTTPS
- Интервью с Bald Po, посвященное веб-безопасности
- Лысый сломанный интерфейсный интервью - резюме тренировки по перекрестным доменам
Другие типы:
- Грязное и сломанное фронтенд-интервью - Promise && Async/Await
- ...
- Лысая сломанная серия больше адресов
что такое кросс домен
Сегодня давайте поговорим о междоменной практике ~ почему нам нужно добавить практику, потому что междоменная вещь, я думаю, вы достаточно видели теоретически, если это интервью, может быть достаточно сказать несколько планов. не позволит вам на самом деле написать код, но действительно ли вы его использовали? Вы действительно понимаете, как это работает? Основываясь на этой точке зрения, я написал следующую кросс-доменную статью, основанную на практике.
В частности см. выше статью "Связанные с веб-безопасностью" должно быть общее понимание. Если вы не поняли, здесь снова в кратком изложении.
При запросе URL-адреса на главной странице URL-адрес в браузере должен находиться в том же домене, что и доменное имя, порт и протокол. Если что-то из этого отличается, это междоменная категория.
Скриншоты с прямым кодом более интуитивно понятны:
// express 起了一个小型服务,并且写了一个接口 /list
app.get('/list', (req, res) => {
const list = [
{
name: 'luffy',
age: 20,
email: 'luffy@163.com'
}, {
name: 'naruto',
age: 24,
email: 'naruto@qq.com'
}
]
res.status(200).json(list);
});
Посещение браузера:
Напишите еще одну html-страницу для вызова этого интерфейса:
<script>
window.onload = function() {
const xhr = new XMLHttpRequest();
xhr.open('GET', 'http://localhost:3000/list');
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
const resData = JSON.parse(xhr.responseText);
console.log(resData);
}
};
xhr.send();
}
</script>
Видно, что это кроссдоменная, думаю, друзья, которые только что изучили фронтенд, но плохо разбираются в бэкенде, часто его увидят.
перекрестный домен: Короче говоря, то, что мы обычно называем междоменным, означает, что в соответствии с ограничениями политики одного и того же происхождения браузеру не разрешено выполнять сценарии других веб-сайтов.
Способы решения кроссдоменности
Существуют различные способы решения междоменных проблем, но, грубо говоря, мы обычно используем только два или три вида, но так как это резюме, то мы разберем всякие странные трюки~
Лично в процессе командной разработки проекта фронтенд не очень подходит для кроссдоменной обработки.Большинство кроссдоменных сценариев должен обрабатывать бэкенд, поэтому здесь лишь краткое обсуждение разработки процесс этого междоменного решения.
Самое популярное междоменное решение — CORS
Если в текущем проекте участвует междоменная проблема, ее следует решить, настроив CORS в бэкэнде. CORS в настоящее время является наиболее распространенным междоменным решением. Междоменное совместное использование ресурсов (CORS) — это механизм, который использует дополнительные заголовки HTTP, чтобы сообщить браузерам, что веб-приложениям, работающим в источнике (домене), разрешен доступ из разных источников. указанный ресурс на исходном сервере.
// 在node端设置一下请求头,允许接收所有源地址的请求
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', '*');
Перезапустите службу и обновите страницу:
Видно, что данные получены, и междоменное решение завершено~
Вообще говоря, это проще, Node.js может напрямую использовать зрелое сообщество.corsстроить планы
Самое классическое междоменное решение — JSONP
Следующее, о чем я хочу поговорить, - это решение JSONP. Не преувеличение, чтобы сказать, что это самая классика. Хотя большинство проектов не используют его, чтобы решить перекрестные решения, до тех пор, пока это интервью и включает в себя перекрестные решения -domain, это в основном спросили. Пункт знаний.
Принцип немологистой лимита
Гомологическая рестрикция является сущностью кросс-домена, то есть нет такой вещи, как гомологичная рестрикция, значит, нет кросс-домена. На самом деле есть некоторые теги, не имеющие ограничений по гомологии —<script>/<link>/<img>. Принцип, который использует JSONP, заключается в том, что эти теги решают междоменные проблемы.
Первый шаг: предположим, что есть внутренние интерфейсы/jsonp/list
// 按钮获取数据
<button onclick="loadJsonpData()">JSONP获取数据</button>
<script>
function loadJsonpData() {
const script = document.createElement('script');
script.src='http://localhost:3000/jsonp/list';
document.body.appendChild(script);
}
</script>
Нажмите кнопку, чтобы<body>Вставьте тег внутрь<script>тег, браузер встречает<script>выполнит содержимое.Ключевой момент, браузер выполнит содержимое скрипта внутри.
Шаг 2: Передняя и задняя стороны согласовывают имя исполнительной функции.
Как упоминалось в первом шаге, передайте указанный URL-адрес через<script>Когда тег будет загружен на страницу, содержимое скрипта будет выполнено. Итак, подумайте о цели нашего междоменного запроса -получить данные. Другими словами, содержимое внутри должно быть исполняемой функцией и передавать нужные нам данные. Таким образом, передняя и задняя части теперь должны согласовать имя исполнительной функции!
Предположим, соглашение здесь таково, что имя функцииcallbackData
Шаг 3: Определите callbackData во внешнем интерфейсе
Как только имя функции выполнения согласовано, передняя часть должна определить его, потому что внутренняя часть возвращает часть исполняемого кода.Если передняя часть не определена, она сообщитcallbackData undefinedошибка.
// 定义 callback 函数,获取后台的 data
function callbackData(data) {
console.log(data, 98989);
}
Шаг 4. Фон возвращает исполняемый код, содержащий данные
Внешний и внутренний интерфейс имеют согласованные имена, а внешний интерфейс имеет определенные функции.Параметры — это данные, которые необходимо получить. Серверной части нужно только отвечать на пакеты данных в функции выполнения.
Обратите внимание, что интерфейс JSONP отличается от обычного интерфейса, он возвращает не данные в формате json, а исполняемую строку, которая будет выполнена интерфейсом.
app.get('/jsonp/list', (req, res) => {
const list = [
{
name: 'luffy',
age: 20,
email: 'luffy@163.com'
}, {
name: 'naruto',
age: 24,
email: 'naruto@qq.com'
}
]
// 把数据塞进执行函数里面
const resData = `callbackData(${JSON.stringify(list)})`;
res.send(resData); // 这里不能使用res.json而是res.send
});
Давайте посмотрим на это:
Как видите, при нажатии на кнопку браузер Network JS запросит только что вставленный<script>Адрес ответа адреса заранее предопределен.callbackData(resData)
И на переднем конце, потому что определениеcallbackData(data), чтобы консоль могла видеть, что содержимое фонового ответа печатается.
Вышеизложенное является основным процессом jsonp. Я не знаю, ясно ли я вам это объяснил. На самом деле это очень просто, но когда я смотрел это раньше, я чувствовал, что все говорили об этом очень официально, и не было фактическая операция, из-за которой многие люди неправильно поняли или прочитали ее. Я не понимаю, здесь я объясню это через фактический код, я думаю, это будет легко понять ~
На самом деле, jsonp тоже можно инкапсулировать, а потом красиво реализовать~ ха-ха. НапримерjqueryЭто встроенная поддержка JSONP.
// jquery jsonp
$.ajax({
url: "http://cross-domain/get_data",
dataType: "jsonp", // 指定服务器返回的数据类型
jsonp: "callback", // 指定参数名称
jsonpCallback: "callbackName" // 指定回调函数
}).done(function(resp_data) {
console.log("Ajax Done!");
});
Я не буду обобщать это здесь, потому что этого достаточно, чтобы понять принцип Текущий интерфейс следует использовать редко, только для интервью.
Кроме того, хотя я часто использую
<script>ярлык, а по факту<img>Этикетки тоже в порядке.
Самое простое междоменное решение — NGINX
Я не буду вводить это много. Если честно, это не междоменное решение для внешнего и внутреннего интерфейса, а относится к уровню эксплуатации и обслуживания. не следует ожидать этого ответа.
Простая версия NGINX решают конфигурацию перекрестной области примерно следующим образом:
server
{
listen 3003;
server_name localhost;
location /ok {
proxy_pass http://localhost:3000;
# 指定允许跨域的方法,*代表所有
add_header Access-Control-Allow-Methods *;
# 预检命令的缓存,如果不缓存每次会发送两次请求
add_header Access-Control-Max-Age 3600;
# 带cookie请求需要加上这个字段,并设置为true
add_header Access-Control-Allow-Credentials true;
# 表示允许这个域跨域调用(客户端发送请求的域名和端口)
# $http_origin动态获取请求客户端请求的域 不用*的原因是带cookie的请求不支持*号
add_header Access-Control-Allow-Origin $http_origin;
# 表示请求头的字段 动态获取
add_header Access-Control-Allow-Headers
$http_access_control_request_headers;
# OPTIONS预检命令,预检命令通过时才发送请求
# 检查请求的类型是不是预检命令
if ($request_method = OPTIONS){
return 200;
}
}
}
Теоретическое междоменное решение — window.name
То, что это теоретическое междоменное решение, означает, что оно действительно может передавать данные между доменами, но используется редко.
Проверьте это,MDN 是这么说的,(如 SessionVars 和 Dojo's dojox.io.windowName ,该属性也被用于作为 JSONP 的一个更安全的备选,来提供跨域通信(cross-domain messaging).但是这俩框架我也确实孤陋寡闻了,还是有应用的并且兼容性还是很好的,除了万年不变的 IE 不一定支持,其他的浏览器都支持。
Давайте сначала кратко понять, чтоwindow.name:
- Каждое окно браузера (вкладка) имеет независимое имя окна, соответствующее ему.
- В одном окне (Вкладка p) от открытого до закрытого перед загрузкой окнавсеСтраницы разделяют одну одновременно
window.name, каждая страница в этом окне связана сwindow.nameИметь разрешение на чтение и запись. -
window.nameЭто текущее окно (вкладка страницы) свойства и не изменится, потому что возникает скачок страницы. -
window.nameЕмкость около 2Мб, формат хранения - строка
Звучит немного бледно, давайте посмотрим на реальный пример.
Выше, вhttp://127.0.0.1:3006уже настроенwindow.name = aaaaa, затем страница переходит кhttp://127.0.0.1:3008, который является междоменным в соответствии с политикой браузера в отношении одного и того же источника.
сцена, но и правильно получил настройки, выставленные на предыдущей страницеwindow.name. Как упоминалось выше, каждое окно является общим, так что, если это другой порт?
// 代码改成新窗口打开
<a target='_blank' href='http://127.0.0.1:3008/'>跳转到3008端口</a>
можно увидеть,window.nameЭто действительно независимо между окнами (вкладками), открываются новые окна,window.nameИнициализация - это пустая строка.
Две картинки вышеwindow.nameформа хранения, наборArray aа такжеObject b,видимыйwindow.nameПри сохранении он будет вызывать собственный объектtoString()Сохраните его позже.
Конечно, если интервьюер действительно спрашивает здесь, поэтому ответ на самом деле не является большой проблемой, но все еще ошибочно, потому что есть особая ситуация, является основным типом нового типа ES6Symbol.
фактическое использованиеwindow.nameДля междоменного сбора данных
Так много было сказано выше, по сути, это просто введениеwindow.nameФункции и использование, по сути, не предполагают междоменного сбора данных, например, в первой демонстрации я настроил его в Awindow.nameЗатем перейдите к B, чтобы получить значение, установленное A. Это называется междоменным? Не было бы удобнее добавить значение к параметру, когда я прыгаю, так что это не реальная сцена. Вот реальный сценарий:
【Описание проблемы】: есть две разные страницы домена A и B,
пройти черезwindow.nameПри загрузке A получаются настройки страницы Bwindow.name.
Давайте сначала подумаем об этом, то, что делает страница B, это не что иное, как установка данных вwindow.name, затем, когда мы загружаем страницу A, мы переходим для ее получения на страницу B. В настоящее время мы не можем перейти к B, а затем обратно к A, потому что получение данных — это асинхронный сценарий, который не обновляет страницу. Ну а когда дело доходит до этого, я почти знаю, это должно быть достигнуто через iframe, то есть страница А открывает iframe того же домена - допустим это proxy.html, мы называем его страницей переноса, и мы открываем это снова на странице передачи. Страница B, получить Bwindow.nameМожно использовать предварительно установленные данные. Весь процесс примерно таков:
Вот часть кода:
http://127.0.0.1:3006/a-data.html -> A 页面
http://127.0.0.1:3006/a-data.html -> proxy 数据中转页面 -> 只是个空页面
http://127.0.0.1:3008/b-data.html -> B 页面
___________________________________________
// b-data.html
<script>
const data = [
{
name: 'luffy',
age: 20
}, {
name: 'naruto',
age: 22
}
]
window.onload = function() {
window.name = JSON.stringify(data);
}
</script>
// a-data.html
<script>
const currentDomain = 'http://127.0.0.1:3006'; // 当前域
const corssDomain = 'http://127.0.0.1:3008'; // 跨域
window.onload = function() {
let flag = false; // 是否获取数据
iframe = document.createElement('iframe'),
loadData = ()=> {
if (flag) {
// 读取B的数据
let data = iframe.contentWindow.name;
console.log(data, 66666);
iframe.contentWindow.document.write('');
iframe.contentWindow.close();
document.body.removeChild(iframe);
} else {
flag = true;
// 加载同域代理文件
iframe.contentWindow.location = `${currentDomain}/proxy.html`;
}
};
iframe.src = `${corssDomain}/b-data.html`;
if (iframe.attachEvent) {
iframe.attachEvent('onload', loadData);
} else {
iframe.onload = loadData;
}
document.body.appendChild(iframe);
}
</script>
Как видно из рисунка выше, A получил данные, переданные страницей B. Как бы это сказать, это слишком сложно, нужно добавить iframe и нужна страница передачи, поэтому ->В итоге,Лично я считаю,window.nameДействительно, теоретическое решение для перекрестного домена должно положиться наwindow.nameразличные функции, но это должно быть сделано в том же окне браузера, и это должно взаимодействовать сiframeИ та же страница переноса домена.
Прямой потомок легендарной программы HTML5 postMessage
Это более продвинутый способ, почему? Из-за предыдущего JSONP илиwindow.name, это причудливая идея.Официальный дизайн его не используется для кросс-доменности или сверления лазеек в дизайне.Что касается CORS и NGINX, то это не-front-end категория. Итак, HTML5 выпустил это сообщение для серьезного «безопасного» междоменного доступа.Может ли разница между настоящим сыном и выбранным сыном быть одинаковой 😂? Но я не знаю почему, я думаю, может быть, этот метод используется меньше, может быть, я невежественен, но я действительно не видел, чтобы люди его использовали.
принцип:otherWindow.postMessage(message, targetOrigin, [transfer]);
Принцип postMessage состоит в том, чтобы полагаться на ссылку на другое окно, и эта ссылка может бытьwindow.open()Возвращенный также может быть contentWindow iframe или может быть назван и проиндексирован.window.frames, Это может быть в других местах, и вы увидите iframe postMessage вместе.
PostMessage также относительно прост, иофициальная документацияВведение тоже достаточно подробное, если интересно, то можете прочитать его внимательно, я буду непосредственно практиковать код здесь:
// A页面
let opener;
function openB () {
opener = window.open('http://127.0.0.1:3008/index.html')
}
// 发送消息
function postMsg() {
const msg = document.getElementById('chatB').value;
opener.postMessage(msg, "http:/127.0.0.1:3008");
}
Логика страницы А очень проста, то есть мы используем страницу Аwindow.open()Откройте B, а затем используйте полученное targetWindow для связи между двумя страницами.
// B 页面
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event) {
// Chrome浏览器兼容
const origin = event.origin || event.originalEvent.origin;
if (origin !== "http://127.0.0.1:3006") {
return;
}
const { data } = event; // 获取到 A 的数据
// 下面是你的逻辑
...
}
На странице B мы слушаемmessageСобытие, а затем определите, является ли это целевой домен, если это целевой домен, получите данные для работы.
Здесь подчеркивается, почему он безопасен, поскольку перед тем, как А свяжется с Б, он определит, является ли он целевым доменом, если нет, то он не будет работать.
Давайте посмотрим на эффект:
только одно предложение哎呦,不错呦~Чтобы описать это, так как A и B закончили отправлять сообщения, затем отправьте Будду на Запад, и мы также закончили писать B для A, что можно рассматривать как упрощенную версию системы чата.
ОК, все равно выглядит очень хорошо, ведь официальное решение очень зрелое, и отправляемые данные тоже могут быть в разных форматах, которые должны быть самыми продвинутыми. Однако, простите меня, даже после написания этой небольшой демонстрации, я все еще не могу представить ее реальный и подходящий сценарий использования, LAN-чат? Возможно, если вы расскажете мне об общении в реальном времени, то я точно не поверю, потому что ниже я представлю более сильных боссов~ Если кто-то использует его много, или использовал в реальных сценариях, вы можете оставить сообщение общайся и дай мне подняться. Знакомься 😄
Другие перекрестные решения
document.domain
Это более бесполезно, но это только в книге на книге или документе, потому что сцена относительно ограничена до предела. Его предел невелик, но ограничение очень велико. Если вы хотите использовать этот способ для междоменного взаимодействия, A и B должны соответствовать следующим условиям:
A: http://aaa.xxx.com:port
B: http://bbb.xxx.com:port
То есть доменные имена первого уровня у A и B одинаковые, доменные имена второго уровня разные, а протокол и номер порта также должны быть одинаковыми.
На основе выполнения вышеуказанных условий две страницы устанавливаются друг к другуwindow.domain = 'xxx.com'Мы можем общаться. . .原谅我穷B一个没有域名给大家展示了。但是说实话也没必要,这种方式何必呢。 . .
WebScoket
Ну, настоящий босс здесь, вот и мы. Когда я говорил о postMessage выше, я сделал небольшую демонстрацию чата A и B. Я также упомянул, что если это действительно сцена общения в чате, уровень босса должен быть Webscoket, что .
Почему Websocket может работать с несколькими доменами?
Проблема как сказать. Во-первых, Websocket здесь действительно считался читерством, и почему? Поскольку мы говорим о кросс-доменном, это означает, что браузер и сервер имеют одинаковые ограничения при обмене данными на основе протокола HTTP. И Websocket просто не основан на протоколе HTTP, который расположен поверх TCP/IP, HTTP-протокола с таким же уровнем протокола связи браузера.
Сейчас слишком сложно писать статью, надо уметь рисовать 😂
Это, пожалуй, топ, как этот, Webcocoket с слоем протокола HTTP такой же, поэтому предел для HTTP Webcocoket, люди не птицы, братья и сестры, почему, черт возьми, вы контролируете меня - но тогда есть маленькая стрелка, Относится к рукопожатию Websocket при установлении соединения (TCP трехстороннее рукопожатие), данные передаются через протокол HTTP, но после установления соединения фактическая стадия передачи данных не требуется для участия в протоколе HTTP. О Webbocket не связано слишком много здесь, потому что эта статья - сказать, что кросс-домен, поскольку вышеупомянутая рассылка, потом посмотрел на веб-сайт, а затем посмотрел на WebSoket Написать то же значение, первые визуализации (простой клиент и сервер для общения):
Видно, что важным моментом Websocket является не решение междоменных проблем, на самом деле никто не должен использовать его для решения междоменных проблем. Его важность заключается в том, что он предоставляет возможность клиенту активно отправлять сообщения, а серверу — активно отправлять сообщения. Если мы используем HTTP, мы обычно просто инициируем запрос от клиента, а сервер отвечает на запрос. Нет возможности активно отправлять сообщения друг другу. Поэтому, если мы не используем Websocket, мы обычно используем AJAX long раунд обучения для установки Таймер постоянно отправляет запросы на обновление данных, что на самом деле является пустой тратой производительности и не очень элегантно. Итак, преимущества Websocket:
- Нет ограничений по одному и тому же происхождению, нет междоменного доступа
- Полнодуплексная связь, обе стороны могут активно отправлять сообщения
- Улучшенная производительность в реальном времени и более высокая гибкость
Применимые сценарии Websocket — это приложения с высокой производительностью в реальном времени, такие как связь, фонд акций и битовые приложения.
Я мало что знаю об этом. Для получения дополнительной информации, пожалуйста, обратитесь к официальной документации и другим связанным статьям.
похожие темы
1. Что такое междоменный и почему он междоменный
2. Расскажите о нескольких способах решения междоменных
3. Расскажите о принципе реализации и процессе JSONP
Суммировать
Хотя вышеперечисленных междоменных решений очень много, CORS и JSONP на самом деле являются двумя наиболее часто используемыми, и их часто подробно спрашивают в интервью.
Итак, сравните CORS и JSONP:
| CORS | JSONP | |
|---|---|---|
| преимущество | Относительно простой, поддерживает как отправку, так и получение | Используемая функция собственного тега, совместимость особенно хороша |
| недостаток | Старые версии IE несовместимы | Единственный способ получить поддержку, и необходимость завершения договора до и после |
Я в основном закончил писать резюме по междоменной практике здесь.Это так утомительно, потому что действительно не просто писать код в дополнение к принципу.Я надеюсь, что это может быть полезно для всех~
Если вы считаете, что это неплохо, звездочка и лайк будут очень признательны.