同源策略:NetSpace公司引入,基於瀏覽器安全,防止瀏覽器收到XSS、CSFR等攻擊。同源,即協議+域名+端口徹底一致。
同源策略:爲保障用戶信息安全,防止惡意網站竊取數據的一種安全策略。
***
「同源」:協議相同、域名相同、端口號相同css
同源策略限制的行爲:html
解決方案:前端
原理:經過script標籤引入的js不受同源策略的限制,而XmlHttpRequest對象受到同源策略的影響。能夠加載跨域服務器上的腳本,用JSONP獲取的不是JSON數據,而是能夠直接運行的JS腳本。vue
eg1:jquery function jsonpCallback(data) { console.log("jsonpCallback: " + data.name) } $.ajax({ url:"http://www.nanhuaqiushui.com:8080/login", type:"get", dataType:"jsonp", data:{ name: $("#name").val(), id: $("#id").val() }, cache: false, timeout: 5000, jsonp: "callback", //jsonp字段含義爲服務器經過什麼字段獲取回調函數的名稱 jsonpCallback:"jsonpCallback", //自定義回調函數名 success:function(data){ console.log("ajax success callback: " + data.name); }, error: function(jqXHR, textStatus, errorThrown){ console.log(textStatus + ' ' + errorThrown); } }) eg2:vue this.$http.jsonp("http://www.nanhuaqiushui.com:8080/login",{ params:{ name: $("#name").val(), id: $("#id").val() }, jsonp: "jsonpCallback" }).then((res) => { console.log(res); }); 服務器端處理: app.get("/login", function(req,res){ console.log("server accept: " + req.query.name, req.query.id); var data = "{" + "name:" + req.query.name + "- server 3001 process" + "," + "id:" + req.query.id + "- server 3001 process" + "}"; var callback = req.query.callback; var jsonp = callback + "(" + data + ")"; console.log(jsonp); res.send(jsonp); res.end(); });
注意:data中字符串拼接,不能直接將JSON格式的data直接傳給回調函數,不然會發生編譯錯誤。
本質:node
<script src = 'http://www.nanhuaqiushui.com:8080/login?callback=jsonpCallback&name=lidachui&id=3001&_=1473164876032'></script>
不足:
1.只能使用GET請求(即時POST也會被轉換成GET請求)。
2.JSONP本質上是經過script標籤的src屬性實現跨域請求的,而非ajax,所以不是經過XMLHttpRequest進行傳輸的,因此沒法註冊success、error等事件監聽函數。jquery
原理:使用自定義的HTTP頭部讓瀏覽器與服務器溝通,從而決定請求或響應是否成功。
Cross-Origin Resource Sharing(CORS)跨域資源共享是一份瀏覽器技術的規範,提供了Web服務從不一樣域傳來沙盒腳本的方法,以避開瀏覽器的同源策略。(現代瀏覽器都支持CORS)
優勢:採用XMLHttpRequest對象傳遞,同時支持GET/POST等多種請求方式,方便調試。是JSONP模式的現代版。web
eg: app.post('/cors',function(req,res){ res.header("Access-Control-Allow-Origin","*"); //設置請求來源不受限制 res.header("Access-Control-Allow-Headers","X-Requested-With"); res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS"); res.header("Content-Type", "application/json;charset=utf-8"); var data = { name: req.body.name + ' - server 3001 cors process', id: req.body.id + ' - server 3001 cors process' }; res.send(data); res.end(); })
優勢:只需服務端設置Access-Control-Allow-Origin便可,前端無需設置。
withCredentials: true // 前端設置是否帶cookieajax
原理:window對象的name屬性很特別,name值在不一樣的頁面(甚至不一樣域名)加載後依舊存在,並且能夠支持很是長的name值(2MB)。
Iframe元素能夠在當前網頁之中,嵌入其餘網頁。每一個iframe元素造成本身的窗口,即有本身的window對象。iframe之中的腳本,能夠得到父窗口和子窗口。可是在同源的狀況下,父窗口和子窗口才能通訊;若是跨域,就沒法拿到對方的DOM。json
var proxy = function(url, callback){ var state = 0; var iframe = document.createElement("iframe"); //加載跨域頁面 iframe.src = url; iframe.onload = function(){ if(state == 0){ //第一次onload(跨域頁)成功後,切換到同域代理頁面 iframe.contentWindow.location = "http://www.nanhuaqiushui.com"; state = 1; }else if(state == 1){ //第二次onload(同域proxy頁)成功後,讀取同域window.name中數據 callback(iframe.contentWindow.name); destroyFrame(); } } } documetn.body.appendChild(iframe); //獲取數據後銷燬這個iframe,釋放內存 function destroyFrame(){ iframe.contentWindow.document.write(""); iframe.contentWindow.close(); document.body.removeChild(iframe); } //請求跨域b頁面數據 proxy("http://www.domain2.com/b.html",function(data){ alert(data); });
postMessage是H5 中新的api,可解決如下問題:
頁面和其打開的新窗口的數據傳遞;
多窗口之間消息傳遞;
頁面與嵌套的iframe消息傳遞;
上面三個場景的跨域數據傳遞。api
跨文本消息傳遞(cross-document messaging),簡稱XDM,指來自不一樣域的頁面間傳遞消息。
postMessage(),參數1表示消息值,參數2表示接收方是來自哪一個域的字符串。
var iframeWindow = document.getElementById("rayframe").contentWindow, iframeWindow.postMessage("A secret","http://www.wrox.com");
接收XDM消息時,會觸發window對象的message事件。這個事件以異步形式觸發,所以從發送消息到接收消息可能通過一段時間的延遲。觸發message事件後,傳遞給onmessage事件對象包含一下三方面重要信息:
1.data:做爲postMessage()第一個參數傳入的字符串數據
2.origin:發送消息的文檔所在的域
3.source:發送消息的文檔的window對象的代理。這個代理對象的主要用於在發送上一條消息的窗口中調用postMessage()方法。
用法:postMessage(data,origin)
父窗口: <iframe src="http://www.xiaokeai.com"></iframe> window.onmessage = function(e){ if(e.origin == "http://www.wrox.com"){ //處理接收到的數據 processMessage(e.data); //可選,向來源窗口發送回執 e.source.postMessage("Received","http://p2p.wrox.com") } } 子窗口: if(window.parent !== window.self){ window.parent.postMessage("xiaohuochai","http://fatherxiaokeai.com"); }
背景:同源策略認爲域和子域隸屬於不一樣的域,所以會被瀏覽器攔截。
方法:若是兩個窗口一級域名相同,只是二級域名不一樣,能夠經過設置document.domain來使其通訊。
經過設置document.domain只能獲取DOM,而Cookie、LocalStorage和IndexedDB沒法獲取。
問題:安全性,當一個站點被攻擊後,另外一個站點也會引發安全漏洞;
若是一個頁面中引入多個iframe,要想跨域訪問,就要都設置爲相同的domain值
1.ngix配置解決iconfont跨域
背景:瀏覽器跨域訪問js\css\img等常規靜態資源被同源策略許可,可是iconfont字體文件(eot|otf|ttf|woff|svg)例外,此時需在ngix的靜態資源服務器中加入配置:;
location / {
add_header Access-Control-Allow-Origin * ;
}
2.ngix反向代理接口跨域
原理:同源策略是瀏覽器的安全策略,不是HTTP協議的一部分。服務器端調用HTTP接口只是使用HTTP協議,不會執行JS腳本,不須要同源策略,也就不存在跨域問題。
實現思路:經過ngix配置一個代理服務器(域名與domain1相同,端口不一樣)作跳板機,反向代理訪問domain2接口,而且能夠順便修改cookie中domain信息,方便當前與cookie寫入,實現跨域登陸。
WebSocket protocol是HTML5一種新的協議。它實現了瀏覽器與服務器全雙工通訊,同時容許跨域通信,是server push技術的一種很好的實現。原生WebSocket API使用起來不太方便,咱們使用Socket.io,它很好地封裝了webSocket接口,提供了更簡單、靈活的接口,也對不支持webSocket的瀏覽器提供了向下兼容。
前端: <div>user input:<input type="text"></div> <script src="./socket.io.js"></script> node後臺: var http = require('http'); var socket = require('socket.io'); // 啓http服務 var server = http.createServer(function(req, res) { res.writeHead(200, { 'Content-type': 'text/html' }); res.end(); }); server.listen('8080'); console.log('Server is running at port 8080...'); // 監聽socket鏈接 socket.listen(server).on('connection', function(client) { // 接收信息 client.on('message', function(msg) { client.send('hello:' + msg); console.log('data from client: ---> ' + msg); }); // 斷開處理 client.on('disconnect', function() { console.log('Client socket has closed.'); }); });
又稱爲片斷標識符,指的是URL的#後面的部分。若是隻是改變片斷標識符,頁面不會從新刷新。
父窗口能夠把信息,寫入子窗口的錨點值
var src = originURL + "#" + data; document.getElementById("myIframe").src = src;
子窗口經過監聽hashchange事件獲得通知
window.onhashchange = checkMessage; function checkMessage(){ var message = window.location.hash; ... }