什么是同源策略
同源策略 (Same-Origin Policy) 最早由 Netscape 公司提出, 所谓同源就是要求, 域名, 协议, 端口相同。非同源的脚本不能访问或者操作其他域的页面对象(如DOM等)。作为著名的安全策略, 虽然它只是一个规范, 并不强制要求, 但现在所有支持 javaScript 的浏览器都会使用这个策略。 以至于该策略成为浏览器最核心最基本的安全功能, 如果缺少了同源策略, web的安全将无从谈起。
同源策略要求三同, 即: 同域, 同协议, 同端口。
同域即host相同, 顶级域名, 一级域名, 二级域名, 三级域名等必须相同, 且域名不能与 ip 对应;
同协议要求, http与https协议必须保持一致;
同端口要求, 端口号必须相同。
什么是跨域?跨域有几种实现形式
只要协议、域名、端口有任何一个不同,都被当作是不同的域,跨域就是访问非本域的资源。
跨域实现方式
1、JSONP
2、CORS
3、降域
4、PostMessage
JSONP 的原理是什么
JSONP是服务器与客户端跨源通信的常用方法。最大特点就是简单适用,老式浏览器全部支持,服务器改造非常小。它的基本思想是,AJAX 无法跨域是受到“同源政策”的限制,但是带有src属性的标签(例如<script>、<img>、<iframe>)是不受该政策限制的,因此通过向页面中动态添加标签来完成对跨域资源的访问,这也是 JSONP 方案最核心的原理。
通常我们使用都是引用的静态资源(主要是 js 文件),其实它也可以用来引用动态资源(php、jsp、aspx等),后台服务被访问后返回一个“JavaScript函数调用”形式的字符串,由于是字符串,因此在后台的时候不会起到任何作用,但到了前台,放入标签之内,就成了一个合法的 JavaScript 函数调用,实参是我们真正需要的数据,被调用的回调函数也已经实现了,因此就会顺利的被调用。
JSONP 最大的优点就是兼容性非常好,其原理决定了即便在非常古老的浏览器上也能够很好的被实现。
JSONP 的主要缺点有两个,一是只能 GET 不能 POST,因为是通过引用的资源,参数全都显式的放在URL里,和 AJAX 没有关系。二是存在安全隐患,动态插入标签其实就是一种脚本注入,会受到跨站脚本攻击。
CORS是什么
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。
简单请求:浏览器直接发出CORS请求。具体来说,就是在头信息之中,增加一个Origin
字段。
非简单请求:是对服务器有特殊要求的请求,比如请求方法是PUT
或DELETE
,或者Content-Type
字段的类型是application/json
。
跨域的解决方式
JSONP
JSONP是服务器与客户端跨源通信的常用方法。利用script标签可以引入其它域的JS这一特性,来实现跨域访问接口。JSONP最大特点就是简单适用,老式浏览器全部支持,服务器改造非常小。但前提是后端支持。
1、动态添加<script>
元素,向服务器发出请求
var change = document.querySelector('.change')
var newsList = document.querySelector('.news-list')
change.addEventListener('click', function(){
var script = document.createElement('script');
script.src= 'http://localhost:8080/getNews?callback=appendHtml'
document.head.appendChild(script);
document.head.removeChild(script);
})
2、用src 中 callback
参数 指定回调函数的名字
function appendHtml(news){
var html = '';
for( var i=0; i<news.length; i++){
html += '<li>' + news[i] + '</li>';
}
newsList.innerHTML = html;
}
})
3、服务器收到这个请求以后,会将数据会放在回调函数的参数位置返回。
app.get('/getNews', function(req, res){
var news = [
"第11日前瞻:中国冲击4金 博尔特再战200米羽球",
"正直播柴飚/洪炜出战 男双力争会师决赛",
"女排将死磕巴西!郎平安排男陪练模仿对方核心",
"没有中国选手和巨星的110米栏 我们还看吗?",
"中英上演奥运金牌大战",
"博彩赔率挺中国夺回第二纽约时报:中国因对手服禁药而丢失的奖牌最多",
"最“出柜”奥运?同性之爱闪耀里约",
"下跪拜谢与洪荒之力一样 都是真情流露"
]
var data = [];
for(var i=0; i<3; i++){
var index = parseInt(Math.random()*news.length);
data.push(news[index]);
news.splice(index, 1);
}
var callback = req.query.callback;
if(callback){
res.send(callback + '('+ JSON.stringify(data) + ')');
}else{
res.send(data);
}
})
JSONP的优点是:它不像XMLHttpRequest
对象实现的Ajax请求那样受到同源策略的限制;它的兼容性更好,在更加古老的浏览器中都可以运行,不需要XMLHttpRequest或ActiveX的支持;并且在请求完毕后可以通过调用callback的方式回传结果。
JSONP的缺点则是:它只支持GET请求而不支持POST等其它类型的HTTP请求;它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript
调用的问题。
CORS
CORS(Cross-Origin Resource Sharing)
跨域资源共享,定义了必须在访问跨域资源时,浏览器与服务器应该如何沟通。CORS
背后的基本思想就是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功还是失败。在服务器中设置响应头字段即可:
res.header("Access-Control-Allow-Origin","url")
CORS与JSONP的使用目的相同,但是比JSONP更强大。
JSONP只支持GET
请求,CORS支持所有类型的HTTP请求。JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。
postMessage
postMessage() 方法允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档、多窗口、跨域消息传递。第二个参数可以是*
但如果你设置了一个URL但不相符,那么该事件不会被分发。
父页面发送消息:
window.frames[0].postMessage('message', origin)
iframe接受消息:
window.addEventListener('message',function(e){
if(e.source!=window.parent) return;//若消息源不是父页面则退出
//TODO ...
});
其中 e 对象有三个重要的属性
- data, 表示父页面传递过来的message
- source, 表示发送消息的窗口对象
- origin, 表示发送消息窗口的源(协议+主机+端口号)
网友评论