同源策略
同源策略是对XHR的一个主要约束,它为通信设置了“相同的域”,“相同的端口”,“相同的协议”一系列限制,浏览器从安全角度出发,只允许在本域下的接口交互,不同源的客户端在没有明确授权的情况下,不能读写限制之外的资源,除非采用被认可的跨域方案。而跨域资源嵌入是被允许的,页面中的连接,重定向和表单提交也是被允许的。
跨域方式
- JSONP
- CORS(Cross-Origin Resource Sharing,跨域资源共享)
- 降域
- postMessage
JSONP的原理
JSONP(JSON with padding)填充式JSON,JSONP主要由回调函数和数据(传入回调函数的JSON数据)组成,因为浏览器允许跨域资源嵌入,所以JSONP是通过在页面内动态地添加<script>,为标签内src添加一个跨域URL,其中包含在之前声明好的回调函数(?callback=回调函数名),当JSONP响应加载完毕以后,则会立即执行。
- 缺点:
- 不能确保从其它域中加载的代码中是否含有恶意代码。
- 确定JSONP请求是否失败并不容易(HTML5中为script元素添加的oneerror事件处理程序并没有得到任何浏览器支持)
<script>
document.querySelector(".change").addEventListener('click',function(){
var newScript = document.createElement("script");
newScript.src = "http://localhost:8080/getItems?callback=appendHtml";
document.head.appendChild(newScript);
document.head.removeChild(newScript);
});
//声明回调函数
function appendHtml(items){
var html = '';
for(var i=0;i < items.length;i++){
html +='<li>' + items[i] + '</li>';
}
console.log(html);
var add = document.querySelector('.ct');
add.innerHTML = html;
}
</script>
var backMs = req.query.callback;
if(backMs){
res.send(backMs + '(' +JSON.stringify(data) + ')' );
} else {
res.send(data);
}
CORS
CORS 全称是跨域资源共享(Cross-Origin Resource Sharing),是一种 ajax 跨域请求资源的方式,支持现代浏览器,IE支持10以上。 实现方式很简单,当你使用 XMLHttpRequest 发送请求时,浏览器发现该请求不符合同源策略,会给该请求加一个请求头:Origin,后台进行一系列处理,如果确定接受请求则在返回结果中加入一个响应头:Access-Control-Allow-Origin; 浏览器判断该相应头中是否包含 Origin 的值,如果有则浏览器会处理响应,我们就可以拿到响应数据,如果不包含浏览器直接驳回,这时我们无法拿到响应数据。
<script>
var btn = document.querySelector(".change")
var ct = document.querySelector(".ctn")
btn.addEventListener("click",function(){
var xhr = new XMLHttpRequest()
xhr.open('get', 'http://haoren.com:8080/getJobs',true)
xhr.send()
xhr.onreadystatechange = function(){
if ( xhr.readyState === 4 && xhr.status === 200){
console.log(xhr.responseText)
render(JSON.parse(xhr.responseText))
}
}
})
function render(newLi){
var html = ''
for(var i = 0; i < newLi.length; i++){
html += '<li>' + newLi[i] + '</li>'
}
ct.innerHTML = html
}
</script>
app.get("/getItems",function(req,res){
var jobs = [
"4444444",
"5555555",
"6666666",
"7777777",
"8888888",
"9999999"
]
var data = []
for(var i = 0; i < 3; i++){
var index = parseInt(Math.random() * jobs.length)
data.push(jobs[index])
}
res.header("Access-Control-Allow-Origin","http://huairen.com:8080") //添加一个响应头
res.send(data)
PostMessage
parent
<div class="main">
<input type="text" placeholder="http://huairen.com:8080">
</div>
<iframe src="http://haoren.com:8080/jiangyu2.html"></iframe>
<script>
document.querySelector('.main input').addEventListener('input',function(){
window.frames[0].postMessage(this.value,'*');
})
window.addEventListener('message',function(e){
document.querySelector('.main input').value = e.data
});
</script>
child
<body>
<input type="text" id="input" placeholder="http://haoren.com:8080">
</body>
<script>
document.querySelector('#input').addEventListener("input",function(){
window.parent.postMessage(this.value,'*')
})
window.addEventListener('message',function(e){
document.querySelector('#input').value = e.data
})
</script>
降域
a.html
<script>
document.querySelector('.main input').addEventListener('input', function() {
console.log(this.value)
window.frames[0].document.querySelector('input').value = this.value
})
document.domain = 'localhost' //做降域处理
</script>
b.html
<script>
document.querySelector('input').addEventListener('input', function() {
console.log(this.value)
window.parent.document.querySelector('input').value = this.value
})
document.domain = 'localhost' //做降域处理
</script>
网友评论