同源策略: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; ... }