跨域 & JSONP

2017-06-24  本文已影响25人  邢烽朔
该理发了....

同源策略

  1. 协议类型(URI Schema)
  2. 相同域名(host name)
  3. 相同端口号(port number)

目的:
是出于安全性考虑,它能够阻止来自恶意网站的脚本通过其他网站的DOM获取其他网站的信息。可以避免CSRF和XSS攻击。

限制:
同源策略限制的是浏览器或者其他提供类似浏览器服务的软件,而且这仅仅是个规范;
同源策略只是限制JavaScript,而图片,css这些是不存在同源策略限制的。


跨域 & 跨域实现形式

跨域顾名思义就是突破同源策略的限制,去不同的域下访问数据。 在某网站的页面上通过js请求其他网站的数据,如两个网站不满足同源策略,那么该请求是为跨域.


JSONP

首先在客户端声明一个callback, 然后把callback的名字传给服务器。此时,服务器先生成 JSON 数据。然后以 javascript 语法的方式,生成一个function , function 名字就是传递上来的参数JSONP.最后将 JSON数据直接以入参的方式,放置到`function 中,这样就生成了一段 js 语法的文档,返回给客户端。客户端浏览器,解析script标签,并执行返回的 javascript 文档,此时数据作为参数,传入到了客户端预先定义好的 callback 函数里.(动态执行回调函数)


CORS

跨域资源共享( CORS )机制允许 Web 应用服务器进行跨域访问控制,从而使跨域数据传输得以安全进行。浏览器支持在 API 容器中(例如 XMLHttpRequest
Fetch )使用 CORS,以降低跨域 HTTP 请求所带来的风险。CORS 需要客户端和服务器同时支持。目前,所有浏览器都支持该机制。


Method.

1. JSONP:

<pre>
//在file协议下测试跨域 <script> $('.change').addEventListener('click', function() { var script = document.createElement('script'); //请求服务器地点 + callback=appendHtml(告诉服务器用此打包) script.src = 'http://localhost:8080/getNews?callback=appendHtml'; document.head.appendChild(script); document.head.removeChild(script); }) //设置好函数.(等待数据来临) function appendHtml(news) { var html = ''; for( var i=0; i<news.length; i++ ) { html += '<li>' + news[i] + '</li>'; } console.log(html); $('.news').innerHTML = html; } function $(id){ return document.querySelector(id); } </script> //Server: app.get('/getNews', function(req, res){ var news = ['one','two','thr','fou','fiv','six','sev','eig','nin'] var data = [];//新数组 for(var i=0; i<3; i++){ //for循环遍历 var index = parseInt(Math.random()*news.length);//随机取0~7作为下标 data.push(news[index]);//推入 news.splice(index, 1);//news.length降一 } var cb = req.query.callback;// if(cb){ res.send(cb + '('+ JSON.stringify(data) + ')');//转换为一个JSON字符串,并发送 }else{ res.send(data); } })
</pre>


2. CORS:

<pre>
`
<script>
//监听事件
$('.change').addEventListener('click', function(){
//Ajax
var xhr = new XMLHttpRequest();
xhr.open('get', 'http://localhost:8080/getNews', true);
xhr.send();
xhr.onreadystatechange = function(){
if(xhr.readyState === 4 && xhr.status === 200){
appendHtml( JSON.parse(xhr.responseText) ) //使用JSON解析响应数据
}
}
})
function appendHtml(news){
var html = '';
for( var i=0; i<news.length; i++){
html += '<li>' + news[i] + '</li>';
}
$('.news').innerHTML = html;
}
function $(id){
return document.querySelector(id);
}
</script>
//Server:
app.get('/getNews', function(req, res){

var news = []
var data = [];
for(var i=0; i<3; i++){
    var index = parseInt(Math.random()*news.length);
    data.push(news[index]);
    news.splice(index, 1);
}
res.header("Access-Control-Allow-Origin", "http://AAA.com:8080"); //(只允许AAA的请求)
res.header("Access-Control-Allow-Origin", "*");  //允许任何请求(粗暴)
res.send(data);

})
`
</pre>


降域 _ Window.domain获取/设置当前文档的原始域部分, 用于 同源策略.

<pre>
//================a.html==================// <div class="main"> <input type="text" placeholder="......"> </div> <iframe src="a.b.com/b.html" frameborder="0" ></iframe> </div> <script> document.querySelector('.main input').addEventListener('input', function(){ console.log(this.value); window.frames[0].document.querySelector('input').value = this.value; }) document.domain = "b.com" </script> //================b.html==================// <script> document.querySelector('#input').addEventListener('input', function(){ window.parent.document.querySelector('input').value = this.value; }) document.domain = 'b.com'; 设置 </script>
</pre>

如果当前文档的域无法识别,那么domain属性会返回null。
根域范围内,Mozilla允许你把domain属性的值设置为它的上一级域。例如,在 developer.mozilla.org 域内,可以把domain设置为 "mozilla.org" 但不能设置为 "mozilla.com" 或者"org"。
Mozilla 会区分 document.domain
属性 **从没有被设定过值 **和 被显示的设定为跟该文档的URL的domain一致的值,尽管这两种状况下,该属性会返回同样的值。两个文档,只有在 document.domain
都被设定为同一个值,表明他们打算协作;或者都没有设定 document.domain
属性并且URL的域是一致的 (如何判断一致),这两种条件下,一个文档才可以去访问另一个文档。如果不是因为这个特殊的策略,每一个站点都会成为他的子域的XSS攻击的对象(例如,https://bugzilla.mozilla.org 可以被来自 https://bug*.bugzilla.mozilla.org 站点的bug附件攻击)。


PostMessage

<pre>
`
//===============a.html================//
<div class="ct">
<h1>使用postMessage实现跨域</h1>
<div class="main">
<input type="text" placeholder="...">
</div>
<iframe src="a.abc.com" frameborder="0" ></iframe>//模拟的一个网址
</div>
<script>

$('.main input').addEventListener('input', function(){
console.log(this.value);
window.frames[0].postMessage(this.value,'*');
})
function $(id){
return document.querySelector(id);
}

</script>
//===============b.html================//
<script>

$('#input').addEventListener('input', function(){
window.parent.postMessage(this.value, '*');
})
window.addEventListener('message',function(e) {
$('#input').value = e.data
console.log(e.data);
});
function $(id){
return document.querySelector(id);
}
</script>
`
</pre>


  1. JSONP 相对危险...
  2. CORS 把Access-Control-Allow-Origin关闭就不能访问了.
  3. 降域 降了一级,达成同源
  4. window.postMessage() 是指定给一个域名发送了请求,发送你想要的东西,你只需要接受就行了。当然你拒绝不要扔了也是可以的
上一篇下一篇

猜你喜欢

热点阅读