什么是同源策略
同源策略(same origin policy),1995年同源政策由 Netscape 公司引入浏览器。目前,所有浏览器都实行这个政策浏览器出于安全方面的考虑,只允许与本域下的接口进行交互。不同源的客户脚本在没有明确授权的情况下,不能读取对方的资源。
同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据
本域指的是
- 同协议:比如都是 http 或者 https
- 同端口:比如都是 80 端口
- 同域名:比如都是
google.com
什么是跨域?跨域有几种实现形式
跨域是指通过一定方式绕过浏览器同源政策的限制,可以与不同域进行交互
目前学习到四种实现形式:
- JSONP
- CORS
- 降域
- postMessage
JSONP 的原理是什么
jsonp 是一种跨域通信的手段,它的原理其实很简单:
- 首先是利用 script 标签的 src 属性来实现跨域。
- 通过将前端方法作为参数传递到服务器端,然后由服务器端注入参数之后再返回,实现服务器端向客户端通信。
- 由于使用 script 标签的 src 属性,因此只支持 get 方法
CORS是什么
-
CORS 是一个 W3C 标准,全称是“跨域资源共享”(Cross-origin resource sharing,它允许浏览器向跨源服务器,发出 XMLHttpRequest 请求,从而克服了 AJAX 只能同源使用的限制
-
CORS 需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于 IE10。
-
整个 CORS 通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS 通信与同源的 AJAX 通信没有差别,代码完全一样。浏览器一旦发现 AJAX 请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。
因此,实现 CORS 通信的关键是服务器。只要服务器实现了 CORS 接口,就可以跨源通信。
根据视频里的讲解演示三种以上跨域的解决方式 ,写成博客
- JSONP
var http = require('http')
var fs = require('fs')
var path = require('path')
var url = require('url')
http.createServer(function(req, res){
var pathObj = url.parse(req.url, true)
switch (pathObj.pathname) {
case '/getNews':
var news = [
"第11日前瞻:中国冲击4金 博尔特再战200米羽球",
"正直播柴飚/洪炜出战 男双力争会师决赛",
"女排将死磕巴西!郎平安排男陪练模仿对方核心"
]
res.setHeader('Content-Type','text/json; charset=utf-8')
if(pathObj.query.callback){
res.end(pathObj.query.callback + '(' + JSON.stringify(news) + ')') // 将数据处理后返回
}else{
res.end(JSON.stringify(news))
}
break;
default:
fs.readFile(path.join(__dirname, pathObj.pathname), function(e, data){
if(e){
res.writeHead(404, 'not found')
res.end('<h1>404 Not Found</h1>')
}else{
res.end(data)
}
})
}
}).listen(8080)
<!DOCTYPE html>
<html>
<body>
<div class="container">
<ul class="news">
</ul>
<button class="show">show news</button>
</div>
<script>
// 通过script标签发送请求
$('.show').addEventListener('click', function(){
var script = document.createElement('script');
script.src = 'http://127.0.0.1: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>
</html>
- CORS
var http = require('http')
var fs = require('fs')
var path = require('path')
var url = require('url')
http.createServer(function(req, res){
var pathObj = url.parse(req.url, true)
switch (pathObj.pathname) {
case '/getNews':
var news = [
"第11日前瞻:中国冲击4金 博尔特再战200米羽球",
"正直播柴飚/洪炜出战 男双力争会师决赛",
"女排将死磕巴西!郎平安排男陪练模仿对方核心"
]
res.setHeader('Access-Control-Allow-Origin','*') // 设置响应头中的属性,允许所有的站点访问
res.end(JSON.stringify(news))
break;
default:
fs.readFile(path.join(__dirname, pathObj.pathname), function(e, data){
if(e){
res.writeHead(404, 'not found')
res.end('<h1>404 Not Found</h1>')
}else{
res.end(data)
}
})
}
}).listen(8080)
<!DOCTYPE html>
<html>
<body>
<div class="container">
<ul class="news">
</ul>
<button class="show">show news</button>
</div>
<script>
$('.show').addEventListener('click', function(){
xhr = new XMLHttpRequest(); // 创建 AJAX 请求
xhr.open('GET','http://127.0.0.1:8080/getNews',true);
xhr.send();
xhr.onload = function(){
appendHtml(JSON.parse(xhr.responseText));
}
})
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>
</html>
- postMessage
postMessage 是 HTML5 新增加的一项功能,跨文档消息传输(Cross Document Messaging),目前:Chrome 2.0+、Internet Explorer 8.0+, Firefox 3.0+, Opera 9.6+, 和 Safari 4.0+ 都支持这项功能,使用起来也特别简单-
首先创建 a.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>postMessage</title> </head> <body> <iframe src="http://localhost:8080/b.html" ></iframe> <script> window.onload = function(){ var targetOrigin = "http://localhost:8080"; window.frames[0].postMessage('看到我发给你的信息没', targetOrigin); } window.addEventListener('message',function(e){ console.log('a.html接收到信息:',e.data); }); </script> </body> </html>
-
创建 b.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>postMessageB</title> </head> <body> <script> window.addEventListener('message',function(e){ if(e.source != window.parent){ return } var data = e.data; console.log("b.html接收到的消息", data); parent.postMessage("我看到你发的消息了", e.origin) }) </script> </body> </html>
-
在浏览器中打开 http://localhos/a.html
跨域成功
参考:MDN
网友评论