同源策略(Same origin Policy)
-
解析
浏览器出于安全考虑,只允许与同域下的接口进行资源交互。
不同域的客户端脚本在没有明确授权的情况下,不能读写对方的资源。 -
限制
不能通过ajax的方法去请求不同源中的文档。
浏览器中不同域的框架之间是不能进行js的交互操作的。 -
同域
协议如 http
;
域名如 jirengu.com
;
端口如 80
。
三者都相同才是同域。
跨域
-
解析
使不同域下的接口也能够进行资源交互的一种技术。 - 实现方式
-
JSONP
(JSON with padding)
解析 一种使用JSON数据的方法
原理 利用<script>标签没有跨域限制,可以引入其他域下JS的特点;
过程
1 定义数据处理函数_fun
2 创建<script>,src=后端接口,最后加个参数 callback=_fun
3 服务端在收到请求后,返还fun(data) 字符串
。
4fun(data)
放在<script>做为js执行。此时会调用fun函数,将data做为参数。
Tip
1 只支持GET请求,不支持POST等其它类型的HTTP请求;
只支持跨域的HTTP请求,不支持跨域的两个页面之间进行JS调用。
2 不受同源策略影响;
兼容性较好。
$('Btn').addEventListener('click', function(){
var script = document.createElement('script');
script.src = 'http://127.0.0.1/getNews?callback=done';
document.head.appendChild(script);
document.head.removeChild(script);
})
function done(data){
}
前端
-------------------------------------------------------------
后端
var cb = req.query.callback;
if(cb){
res.send(cb + '('+ JSON.stringify(data) + ')');
}else{
res.send(data);
} -
CORS
(Cross-origin resource sharing 跨域资源共享)
解析 一种 ajax 跨域请求资源的方式
原理 使用自定义的 HTTP 头部,让服务器与浏览器进行沟通。
过程
1 使用XMLHttpRequest
发送请求时,浏览器会添加请求头:Origin
2 后台确定接受请求,在返回结果中添加响应头:Access-Control-Allow-Origin
3 由浏览器判断响应头
中是否包含Origin
值
4 如果包含浏览器会处理响应,返回响应数据;如果不包含浏览器直接驳回。
Tip
1 支持所有类型的 HTTP 请求。
2 兼容性较差。
$('.change').addEventListener('click', function(){
var xhr = new XMLHttpRequest();
xhr.open('get', 'http://b.jrg.com:8080/getNews', true);
xhr.send();
xhr.onreadystatechange = function(){
if(xhr.readyState === 4 && xhr.status === 200){
done( JSON.parse(xhr.responseText) )
}
}
})
前端
-------------------------------------------------------------
后端
res.header("Access-Control-Allow-Origin", "http://a.jrg.com:8080");
res.send(data); -
降域
解析 主域相同的时候,把两个子域设置成相同的父域
过程 document.domain + iframe
document.querySelector('.a input').addEventListener('input',function(){
window.frames[0].document.querySelector('input').value = this.value;
})
document.domain = "jrg.com"
A子域
-------------------------------------------------------------
B子域
document.querySelector('.b input').addEventListener('input', function(){
window.parent.document.querySelector('input').value = this.value;
})
document.domain = 'jrg.com'; -
window.postMessage()
解析 HTML5 的一个新特性,用来向其他所有的window对象发送消息。
原理 不同的框架之间可以获取window对象。
Tip
必须等所有的脚本执行完才发送MessageEvent,如果在函数执行的过程中调用,就会让后面的函数超时无法执行。
$('.a input').addEventListener('input', function(){
window.frames[0].postMessage(this.value,'');
})
window.addEventListener('message',function(e) {
$('.main input').value = e.data
});
A子域
-------------------------------------------------------------
B子域
$('.b input').addEventListener('input', function(){
window.parent.postMessage(this.value, '');
})
window.addEventListener('message',function(e) {
$('#input').value = e.data
});
应用
Tip
如何建立两个不同域的网页用来测试?(写给负基础同学如我)
1 安装自带npm的node what?
1.1 下载 这个就行
1.2 安装一路next
1.3 配置环境变量 how
1.4 打开 右键+shift => 此处打开命令行窗口
ok
1.5 测试 node -v/返回版本号 => nmp -v/返回版本号
ok
2 安装mock-server what?
npm install -g server-mock
3 修改hosts how
127. 0. 0.1 a.xxx.com
4 打开本地服务器
4.1 测试文件夹下,调出node窗口
4.2 mock start
5 打开浏览器
5.1 a.xxx.com:8080/test1.html
在a域打开测试文件夹下test1
5.2 b.xxx.com:8080/test2.html
在b域打开测试文件夹下test2