前端跨域
来源:互联网 发布:mac上用word办公软件 编辑:程序博客网 时间:2024/06/05 20:17
跨域问题
在几次的面试中,都被问到前端的跨域方案问题。在实际的项目中,也总是遇到。这篇文章是在看那些年,那些跨域问题 后的笔记。
在这篇文章中理解什么是跨域 JavaScript跨域(1):什么是跨域,如何跨域
具体策略限制情况可看下表
http://www.a.com/b.js 同一域名下 允许 http://www.a.com/lab/a.js
http://www.a.com/script/b.js 同一域名下不同文件夹 允许 http://www.a.com:8000/a.js
http://www.a.com/b.js 同一域名,不同端口 不允许 http://www.a.com/a.js
https://www.a.com/b.js 同一域名,不同协议 不允许 http://www.a.com/a.js
http://127.0.0.100/b.js 域名和域名对应ip 不允许 http://www.a.com/a.js
http://script.a.com/b.js 主域相同,子域不同 不允许 http://www.a.com/a.js
http://a.com/b.js 同一域名,不同二级域名(同上) 不允许 http://www.a.com/a.js
http://www.b.com/b.js 不同域名 不允许
前端跨域
- JSONP
- document.domain
- window.name
- window.postMessage
JSONP
JSONP 简介
原理
利用<script>
标签可以可以访问别的域名下的文件,并执行。
代码:在www.a.com
中请求www.b.com
的数据
script = document.createElement('script');script.type = 'text/javascript';script.src = 'http://www.b.com/getdata?callback=demo';
过程
- a浏览器:发出请求http://www.b.com/getdata?callback=demo
- b服务器,接到请求,JSONP技术中服务器会接受回调函数名作为请求参数(这里是demo),把数据{data:’message’} 包装好, 最终返回的是demo({data:’message’})。
- a浏览器获得 b服务器返回的数据
demo({data:'message'})
,其作为JavaScript代码来执行。 - 只要在a的页面中 声明 demo 函数来处理数据就行。
示例:
function demo(data){ //处理数据}
jQuery
在jQuery中 使用$.ajax()
方法时,将 dataType
设置为jsonp
即可。
代码如下:
$.ajax({ url: 'http://www.b.com/getData.do', dataType: 'jsonp', jsonp: "callback", jsonpCallback: "dosomething" success: function(cb) { console.log(cb); }, error: function(cb) { console.log(cb); }});
在这里找到了一些解释
参数:
- dataType: ‘jsonp’,用于表示这是一个 JSONP 请求。
- jsonp: ‘callback’,用于告知服务器根据这个参数获取回调函数的名称,通常约定就叫 callback。
- jsonpCallback: ‘dosomething’,回调函数的名称,也是前面callback参数的值。
实际发送出来的完整请求长这样:http://www.b.com/getData.do?callback=dosomething&_=1471419449018
。后面的随机字符串是jQuery加上的。
在那些年,那些跨域问题 中说
不指定回调名,可省略callback参数,会由jQuery自动生成
如果没有指定 jsonCallback
如:
$.ajax({ url: 'http://www.b.com/getdata?callback=?', //不指定回调名,可省略callback参数,会由jQuery自动生成 dataType: 'jsonp', success: function(data) { console.log(data.msg); }});
如果请求后拼参数callback=?
,即没有指定回调函数名称, 则jQuery会动态创建一个值赋给这个?,服务端debug可以看到这个值,格式是这样的:
那么jQuery会创建一个值,会执行$.ajax
内部的success
方法或error
方法 。
要注意的点
它只支持GET请求,这是由于该技术本身的特性所决定的。
document.domain
document.domain:获取/设置当前文档的原始域部分, 用于同源策略.
如,来自www.a.com
想要获取document.a.com
中的数据。只要基础域名相同,便可以通过修改document.domain为
基础域名的方式来进行通信,但是需要注意的是协议和端口也必须相同。
//document.a.comdocument.domain = "a.com";
//www.a.comdocument.domain = "a.com"var iframe = document.createElement('iframe');iframe.src = 'http://document.a.com';iframe.style.display = 'none';document.body.appendChild(iframe);iframe.onload = function() { var targetDocument = iframe.contentDocument || iframe.contentWindow.document; //可以操作targetDocument}
HTML DOM IFrame 对象
window.name
原理
- window.name属性就可以被共享
window.name这个全局属性是用来获取和设置窗口名称的
实践
在页面a.html
(8080端口
)中 跨域拿b.html
(8081端口
)的数据
<h1>这是页面A</h1> <script type="text/javascript"> var iframe = document.createElement('iframe'); // iframe.style.display = 'none'; var isLoad = false document.body.appendChild(iframe); iframe.onload = function (){ if(isLoad){ var data = JSON.parse(iframe.contentWindow.name); //拿到name值 document.write(data); }else{ iframe.contentWindow.location = 'http://localhost:8081/html/ziazan/b.html'; isLoad = true; } } </script>
在b.html
中设置 window.name
的值。
<h1>这是页面B</h1> <script> var data = { name:'ziazan', age:'24' } window.name = JSON.stringify(data);//name属性只支持字符串,支持最大2MB的数据 document.write('data in pageB window.name='+ window.name) </script>
运行结果:
(注:iframe.contentDocument 与 iframe.contentWindow 的区别)
报错:
Uncaught DOMException: Blocked a frame with origin “http://localhost:8080” from accessing a cross-origin frame.
此方法失败,但是在同域下,做数据的传递还是可以的。
window.postMessage
window.postMessage(message,targetOrigin)
message: 要传递的对象,只支持字符串信息
targetOrigin:目标域,需要注意的是协议,端口和主机名必须与要发送的消息的窗口一致。如果不想限定域,可以使用通配符“*”,但是从安全上考虑,不推荐这样做。
示例
a.html
(8080端口
)中 发送数据给b.html
(8081端口
);
<h1>这是页面A,发送消息</h1> <button id="sendMsg">发送data</button> <br> <iframe id="iframe_b" src="http://localhost:8081/html/ziazan/b.html" frameborder="0"></iframe> <script type="text/javascript"> var data = { name:'ziazan', age:'24' } var btn = document.getElementById('sendMsg'); var iframe_b = document.getElementById('iframe_b').contentWindow; btn.addEventListener('click',function(){ iframe_b.postMessage(JSON.stringify(data),'http://localhost:8081/html/ziazan/b.html'); }) </script>
<h2>这是页面B,接受消息</h2> <div id="msg"></div> <script> window.addEventListener('message',function(e){ document.getElementById('msg').innerHTML = e.data; }) </script>
运行结果
疑问
现在是a.html
向 b.html
发送消息,如果是页面a.html
要获取b.html中
的数据呢? window.postMessage
是不是只能是父到子的过程?
未完待续…
服务器跨域
- 反向代理
- CORS
- 优化 CORS
- 前端跨域杂谈
- 前端跨域解决方法
- 前端跨域整理
- 前端跨域整理
- 前端跨域解决
- 前端跨域问题
- 前端跨域详解
- 前端跨域问题
- 前端跨域
- 前端跨域问题
- 前端跨域
- 前端跨域访问
- 前端跨域策略
- 前端跨域问题
- 前端跨域
- 前端跨域大全
- 前端跨域
- 前端跨域解决方案
- 文章标题
- Java读取Excel文件
- OpenCV Python教程(2、图像元素的访问、通道分离与合并)
- Html5页面开发app之查询按钮悬浮窗
- 存储管理
- 前端跨域
- hrbust 1143 泉水(深搜的简单应用)
- Tomcat 7 配置MySQL/Oracle JDBC
- zookeeper 工具类以及利用InterProcessLock 创建分布式锁
- Hibernate5 的ServiceRegistory的用法
- 直接在低版本IE6/7/8浏览器中使用HTML5的audio和video标签播放视频音频的办法
- C++实验4——输出星号图
- RecycleView中UI更新
- 6.0申请权限封装修改版