跨源通訊的幾種方式 1.JSONP 2.iframe*** 3.window.postMessage() 4.XMLHttpRequest level 2javascript
跨源限制
在瀏覽器裏
對源(url協議,主機名,端口號)不一樣的通訊進行限制,在web領域 爲了確保安全,只有同源的通訊才能被容許進行,稱爲同源策略
雖然能夠在html裏使用iframe以實如今一個頁面中同時顯示來自不一樣域的文檔,不過js仍然只能訪問同一源的文檔
若是文檔的url和iframe的不一樣,則沒法經過文檔中包含的js對iframe內的dom進行操做,而iframe內的js也沒法操做文檔裏的dom
若是不這樣 ,就會發生諸如不一樣域的cookie可以互相訪問等安全問題php
對於XMLHttpRequest來講,同源策略的含義是,一個XMLHttpRequest對象只能發送至一個特定的服務器,即提供了使用該XMLHttpRequest對象的文檔下載服務器
跨源通訊css
js裏的跨源通訊
JSONP
iframe***
window.postMessage()
XMLHttpRequest level 2html
1.JSONP
利用script標籤的src將其它域的js文件載入,若是在此處動態建立script標籤的話,就能實現對其它域中數據的動態讀取
不過僅僅是取得了數據,還沒法在客戶端使用。所以產生jsonp(json with padding ,padding指向json數據中添加函數名)
服務端會對數據添加函數名後返回
代碼示例java
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>title> <script src="//cdn.bootcss.com/jquery/3.1.1/jquery.min.js">script>head><body><script>var url="http://b.cn/do.php?callback=foo";//注意 foo函數的定義要先於 引入 url裏的內容function foo(res){ console.log(res); console.log(res.a); }function loadData(url){ var elem=document.createElement('script'); elem.src=url; document.getElementsByTagName('head')[0].appendChild(elem); } loadData(url);script>body>html>
b.cn/do.phpjquery
<?php$arr=['a'=>'ajax','b'=>'bbc'];$callback=$_GET['callback'];$json=$callback."(".json_encode($arr).");";echo $json; //foo({"a":"ajax","b":"bbc"});?>
請求的內容是執行代碼的內容,在客戶端是定義聲明部分
jsonp的缺點
沒法在post請求類型中使用
只能作到動態建立script標籤並讀取數據而沒法從客戶端發出數據web
2. XMLHttpRequest level 2
XMLHttpRequest沒法跨源通訊
在XMLHttpRequest level2中 只要服務器端許可就能夠實現ajax
a.cn/a.html算法
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>title> <script src="//cdn.bootcss.com/jquery/3.1.1/jquery.min.js">script>head><body><div class="btn" style="cursor: pointer;text-align:center;width: 100px;height: 50px;line-height:50px;color:white;background: green">clickdiv><script>$(function(){ $(".btn").click(function(){ var xhr=new XMLHttpRequest(); xhr.onreadystatechange=function(){ var state=xhr.readyState; if(state==4){ console.log(xhr.getAllResponseHeaders()); } } xhr.open('GET','http://b.cn/do.php?a=1&b=2'); xhr.withCredentials=true; //默認不發送cookie的,當設個參數設置爲true服務端 Access-Control-Allow-Origin 必須明確指定 不可爲* 並且必須設置 header('Access-Control-Allow-Credentials:true'); xhr.setRequestHeader("content-type",'multipart/form-data');// xhr.setRequestHeader("content-type",'application/x-www-form-urlencoded'); xhr.send('p1=1'); }); });script>body>html>
http://b.cn/do.php 代碼
<?phpheader('Access-Control-Allow-Origin:http://a.cn');header('Access-Control-Allow-Credentials:true');header('Access-Control-Allow-Methods:POST');var_dump($_POST);var_dump($_GET);var_dump(file_get_contents("php://input"));var_dump($_COOKIE);
關於跨源發送cookie json
xhr.withCredentials=true;
這裏跨源指的是 跨的二級的域,根域必須相同,並且cookie的域必須是根域
好比 a.a.cn能夠經過這裏所說的跨源 在向b.a.cn發送ajax請求時 帶上 .a.cn下的cookie
不要覺得 域在.a.cn下的cookie ,a.a.cn在向b.a.cn發請求時 會自動帶上
也不要認爲cookie的跨源能跨根域,是不可能的
3.postMessage()
window.postMessage 是一個安全的跨源通訊的方法。通常狀況下,當且僅當執行腳本的頁面使用相同的協議(一般都是 http)、相同的端口(http默認使用80端口)和相同的 host(兩個頁面的document.domain 的值相同)時,才容許不一樣頁面上的腳本互相訪問。 window.postMessage 提供了一個可控的機制來安全地繞過這一限制,當其在正確使用的狀況下。
調用 window.postMessage時,將分發一個MessageEvent事件到目標窗口, 在全部掛起必須執行的腳本完成後. (例如:當一個事件處理程序調用window.postMessage時,仍剩餘事件處理程序, 先前的掛起等待超時等)。MessageEvent 有消息類型,它被設置爲第一個參數值提供給window.postMessage的data屬性, 對應的window調用window.postMessage的時候,window.postMessage主文檔的來源的origin屬性被稱爲源屬性,指哪一個調用window.postMessage的窗口。 (事件的其餘標準屬性都存在與對應的預期值。)
otherWindow.postMessage(message, targetOrigin);
a.cn/a.html
<!DOCTYPE html><html><head> <title>Post Messagetitle>head><body><div style="width:200px; float:left; margin-right:200px;border:solid 1px #333;"> <div id="color">Frame Colordiv>div><div> <iframe id="child" src="http://b.cn/b.html">iframe>div><script type="text/javascript"> window.onload=function(){ window.frames[0].postMessage('getcolor','http://b.cn'); } window.addEventListener('message',function(e){ console.log('a:',e); var color=e.data; document.getElementById('color').style.backgroundColor=color; },false);script>body>html>
b.cn/b.html
<!doctype html><html><head> <style type="text/css"> html,body{ height:100%; margin:0px; } style>head><body style="height:100%;"><div id="container" onclick="changeColor();" style="widht:100%; height:100%; background-color:rgb(204, 102, 0);"> click to change colordiv><script type="text/javascript"> var container=document.getElementById('container'); window.addEventListener('message',function(e){ if(e.source!=window.parent) return; var color=container.style.backgroundColor; window.parent.postMessage(color,'*'); },false); function changeColor () { var color=container.style.backgroundColor; if(color=='rgb(204, 102, 0)'){ color='rgb(204, 204, 0)'; }else{ color='rgb(204,102,0)'; } container.style.backgroundColor=color; window.parent.postMessage(color,'*'); }script>body>html>