Добавить Автора
Блог:yeaseonzhang.github.io
Оригинальная ссылка
Кроссдоменные проблемы часто возникают в процессе разработки, и есть много решений для решения междоменных проблем.Далее давайте разберем общие методы междоменного интерфейса.
Та же политика происхождения
за чтоперекрестный домен,перекрестный доменотносительно гомологии. Если протокол, доменное имя и порт совпадают, тогомология.
браузер черезТа же политика происхожденияОграничивает взаимодействие документов или сценариев, загруженных из одного источника, с ресурсами из другого источника. Это ключевой механизм безопасности для изоляции потенциально вредоносных файлов, выдержки изMDN.
Общие решения
document.domain
Эта схема в основном используется для междоменных ситуаций, когда основной домен один и тот же, а поддомены разные. Например:https://jdc.jd.com/
а такжеhttps://www.jd.com/
.
вwww.jd.com/открыть одинjdc.jd.com/, доменное имя JDCjdc.jd.com/
, который выполняется через консольdocument.domain = 'jd.com'
;. Принудительно настроить основной домен для достижения того же источника.
var jdc = window.open('https://jdc.jd.com/');
// JDC 页面加载完成后执行
var divs = jdc.document.getElementsByTagName('div');
$(divs).css('border', '1px solid red');
Обычная практика - пройтиiframe
加载一个跨域页面资源。 потому чтоwindow.open
Данным методом будет запрещено разговаривать в браузере.
<iframe id="sub" src="http://sub.domain.com/index.html"></iframe>
<script>
var username = 'yeseonzhang';
</script>
<script>
document.domain = 'domain.com';
console.log(window.parent.username);
</script>
location.hash
Этот междоменный подход в основномустановить/слушатьХэш-часть URL-адреса используется для междоменного взаимодействия, а третья страница необходима для помощи.
На приведенном выше рисунке показано отношение включения трех страниц, аhash
процесс передачи.
<iframe id="iframe-b" src="http://domain-b.com/b.html"></iframe>
<script>
var bPage = document.getElementById('iframe-b');
/* step 1 */
bPage.src = bPage.src + '#user=yeaseonzhang';
function cb (res) {
console.log(res);
}
</script>
<iframe id="iframe-c" src="http://domain-a.com/c.html"></iframe>
<script>
var cPage = document.getElementById('iframe-c');
window.onhashchange = function () {
/* step 2 */
cPage.src = cPage.src + location.hash;
}
</script>
<script>
window.onhashchange = function () {
/* step 3 */
window.parent.parent.cb('success: ' + location.hash);
}
</script>
из-застраницаа такжеc страницаэто тот же ресурс домена, поэтомуc страницав состоянии пройтиwindow.parent.parent
доступстраницаресурс.
window.name
Эта схема аналогичнаlocation.hash
, которому должна помочь третья страница.window.name
Свойства используются для получения/установки имени окна. Следует отметить, что текущее окноwindow.name
Он не изменится из-за перезагрузки страницы и переходов, поэтому вы можете использовать эту функцию для конвертации междоменныхwindow.name
Читать, перенаправляя на ту же страницу домена.
<script>
var iframe = document.createElement('iframe');
/* step 1 加载跨域页面 */
iframe.src = 'http://domain-b.com/b.html';
var domain = 'diff';
/* 监听iframe加载 */
iframe.onload = function () {
if ('diff' == domain) {
/* step 2 重定向到同域页面 */
iframe.contentWindow.location = 'http://www.domain-a.com/c.html';
domain = 'same';
} else if ('same' == domain) {
/* 获取同域资源的window.name信息 */
cb(iframe.contentWindow.name);
/* 清空数据 */
iframe.contentWindow.name = '';
}
}
function cb (res) {
console.log(JSON.parse(res));
}
</script>
<scirpt>
/* 写入相关数据 */
var obj = {
username: 'yeaseonzhang'
}
window.name = JSON.stringify(obj);
</script>
Тот же доменc страница, может быть пустой страницей, никаких действий не требуется.
JSONP
JSONP(JSON с дополнением) даJSONспособ его использования. Таким образом, пользователь может пройтиcallback
Параметр передается серверу, и когда сервер возвращает данные, параметр обратного вызова будет использоваться в качестве имени функции для переноса данных JSON.
Как мы все знаем, все html-страницы сsrc
метка атрибута (<img>
,<script>
а такжеiframe
) имеют междоменные возможности. Поэтому самый простой способ реализовать это — динамически загружать JS.
клиент
function todo(data){
console.log('The author is: '+ data.name);
}
var script = document.createElement('script');
/* callback参数,用来指定回调函数的名字。 */
script.src = 'http://www.yeaseonzhang.com/author?callback=todo';
document.body.appendChild(script);
Сервер
/* 服务器收到这个请求以后,会将数据放在回调函数的参数位置返回。 */
todo({"name": "yeaseonzhang"});
todo()
Функция будет выполняться как глобальная функция, пока она определенаtodo()
функция, функция будет вызвана немедленно.
postMessage
window.postMessage
— это безопасный API обмена сообщениями на основе событий в HTML5.
otherWindow.postMessage(message, targetOrigin, [transfer]);
postMessage()
, метод содержит три параметра:
-
message
: содержание сообщения -
targetOrigin
: принять источник окна сообщения, то есть "протокол + имя домена + порт". Также можно установить подстановочные знаки*
, отправить на все окна -
transfer
: необязательный параметр (логическое значение), представляющий собой строку, передаваемую одновременно с сообщением.Transferable
Объекты. Право собственности на эти объекты будет передано получателю сообщения, а отправитель больше не сохранит право собственности.
отправительа такжеполучательможет пройтиmessage
События, слушайте сообщения друг друга.message
объект событияevent
Содержит три свойства:
-
event.source
: ссылка на объект окна, отправивший сообщение, который можно использовать для установления двусторонней связи между двумя окнами. -
event.origin
: URI для отправки сообщения -
event.data
: содержание сообщения
отправитель:domain-a.com/a.html
<script>
var newWindow = window.open('http://domain-b.com/b.html');
/* 向b.html发送消息 */
newWindow.postMessage('Hello', 'http://domain-b.com/b.html');
/* 双向通信,接收b.html的回复消息 */
var onmessage = function (event) {
var data = event.data;
var origin = event.origin;
var source = event.source;
if (origin == 'http://domain-b.com/b.html') {
console.log(data); //Nice to see you!
}
};
window.addEventListener('message', onmessage, false);
</scirpt>
Получатель:domain-b.com/b.html
<script>
var onmessage = function (event) {
var data = event.data;
var origin = event.origin;
var source = event.source;
if (origin == 'http://domain-a.com/a.html') {
console.log(data); //Hello
/* 回复a.html的消息 */
source.postMessage('Nice to see you!', 'http://domain-a.com/a.html');
}
};
window.addEventListener('message', onmessage, false);
</script>
WebSocket
WebSocket
Это новый протокол HTML5, реализующий полнодуплексную связь между браузером и сервером, а также междоменное решение.MDN.
/* websocket协议为ws/wss, 类似http/https的区别 */
wsUrl = 'wss://127.0.0.1:8090/ws/';
/* 发送 */
ws = new WebSocket(wsUrl);
/* 连接成功建立时调用 */
ws.onopen = function (event) {
console.log("websocket command onopen");
var msg = {
username: 'YeaseonZhang'
}
/* 通过 send() 方法向服务端发送消息,参数必须为字符串 */
ws.send(JSON.stringify(msg));
};
/* 服务端向客户端发送消息时调用 */
ws.onmessage = function (event) {
/* event.data包含了服务端发送过来的消息 */
console.log("websocket command onmessage: " + event.data);
if (event.data === 'success') {
/* 通过 close() 方法断开websocket连接 */
ws.close();
}
};
/* 连接被关闭时调用 */
ws.onclose = function (event) {
console.log("websocket command onclose: " + event.data);
};
/* 出现错误时调用 */
ws.onerror = function (event) {
console.log("websocket command onerror: " + event.data);
};
WebSocket
Преимущество заключается в том, что в дополнение к достижению междоменной связи также имеется возможность поддерживать долгосрочные соединения без необходимости достижения режима реального времени посредством опроса.
CORS
CORS
Это стандарт W3C, полное название — «Совместное использование ресурсов кросс-происхождения» (Cross-origin resource sharing).
Только back-end поддерживает одноклассники, а front-end не нужно делать много лишней работы (кроме переноскиcookie
).
Пока ответ, возвращаемый сервером, содержит информацию заголовкаAccess-Control-Allow-Origin: domain-name
,domain-name
Чтобы разрешить междоменные доменные имена, его также можно установить на*
, браузер разрешит этот междоменный запрос.
Эпилог
Вышеупомянутое междоменное решение, которое я знаю, надеюсь, поможет вам.