聊聊js跨域
推荐先读一下这篇文章:
https://segmentfault.com/a/1190000012469713
http://www.dailichun.com/2017/03/22/ajaxCrossDomainSolution.html
在聊这个问题之前,不妨先思考一下什么事跨域以及解决跨域的原理 ( ajax跨域只是属于浏览器"同源策略"中的一部分,其它的还有Cookie跨域iframe跨域,LocalStorage跨域等这里不做介绍);
如何解决ajax跨域
跨域常用解决方法:
- JSONP方式
- CORS方式
- 代理请求方式
- 图片Ping
- 设置document.domain = my.com
- 使用websocket通信
一般ajax跨域解决就是通过JSONP解决或者CORS解决,如以下:(注意,现在已经几乎不会再使用JSONP了,所以JSONP了解下即可)
(一)JSONP方式解决跨域问题
jsonp解决跨域问题是一个比较古老的方案(实际中不推荐使用),这里做简单介绍(实际项目中如果要使用JSONP,一般会使用JQ等对JSONP进行了封装的类库来进行ajax请求)
实现原理
JSONP之所以能够用来解决跨域方案,主要是因为 <script> 脚本拥有跨域能力,而JSONP正是利用这一点来实现。具体原理如图
实现流程
JSONP的实现步骤大致如下(参考了来源中的文章)
客户端网页网页通过添加一个<script>元素,向服务器请求JSON数据,这种做法不受同源政策限制
function addScriptTag(src) {
var script = document.createElement('script');
script.setAttribute("type","text/javascript");
script.src = src;
document.body.appendChild(script);
} window.onload = function () {
addScriptTag('http://example.com/ip?callback=foo');
} function foo(data) {
console.log('response data: ' + JSON.stringify(data));
};
请求时,接口地址是作为构建出的脚本标签的src的,这样,当脚本标签构建出来时,最终的src是接口返回的内容
- 服务端对应的接口在返回参数外面添加函数包裹层
foo({
"test": "testData"
});
- 由于<script>元素请求的脚本,直接作为代码运行。这时,只要浏览器定义了foo函数,该函数就会立即调用。作为参数的JSON数据被视为JavaScript对象,而不是字符串,因此避免了使用JSON.parse的步骤。
注意,一般的JSONP接口和普通接口返回数据是有区别的,所以接口如果要做JSONO兼容,需要进行判断是否有对应callback关键字参数,如果有则是JSONP请求,返回JSONP数据,否则返回普通数据
使用注意
基于JSONP的实现原理,所以JSONP只能是“GET”请求,不能进行较为复杂的POST和其它请求,所以遇到那种情况,就得参考下面的CORS解决跨域了(所以如今它也基本被淘汰了)
(二)CORS解决跨域问题
CORS的原理上文中已经介绍了,这里主要介绍的是,实际项目中,后端应该如何配置以解决问题(因为大量项目实践都是由后端进行解决的),上面链接文章整理了一些常见的后端解决方案:
(三)代理请求方式解决接口跨域问题
注意,由于接口代理是有代价的,所以这个仅是开发过程中进行的。
与前面的方法不同,前面CORS是后端解决,而这个主要是前端对接口进行代理,也就是:
- 前端ajax请求的是本地接口
- 本地接口接收到请求后向实际的接口请求数据,然后再将信息返回给前端
- 一般用node.js即可代理
关于如何实现代理,这里就不重点描述了,方法和多,也不难,基本都是基于node.js的。
搜索关键字node.js,代理请求即可找到一大票的方案。
(四)图片Ping
我们知道,一个网页可以从任何网页加载图像,不用担心跨域不跨域,所以,我们就可以利用图片不受“同源限制”这一点进行跨域通信。
我们利用JS创建一个新的Image对象,并把src属性设置为指向请求的地址,通过监听onload和onerror事件来确定是否接受到了响应。响应的数据可以是任意内容,但通常是像素图或204响应。
需要注意的是,新图像元素只要设置了src属性就会开始下载,所以我们这里的事件一定要在指定src属性之前绑定,这也是为什么我们这里不需要把img标签插入DOM 的原因。
<body>
<button id="Ping">图像Ping发送请求</button>
<script>
var btn=document.getElementById('Ping');
btn.onclick=function () {
var img=new Image();
img.onload=img.onerror=function () {
alert("Done");
};
img.src="http://localhost:8081/img?name=Joy";
}
</script>
</body>
//服务器代码
app.get('/img',function (req,res) {
res.send("我是一张图片");
});
这种方式优点是很明显的:兼容性非常好,缺点就是:只能发生GET请求,而且无法获取响应文本。
聊聊js跨域的更多相关文章
- 5种处理js跨域问题方法汇总(转载)
1.JSONP跨域GET请求 ajax请求,dataType为jsonp.这种形式需要请求在服务端调整为返回callback([json-object])的形式.如果服务端返回的是普通json对象.那 ...
- JS跨域(ajax跨域、iframe跨域)解决方法及原理详解(jsonp)
这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据.只要协议.域名.端口有任何一个不同,都被 ...
- 前端Js跨域方法汇总—剪不断,理还乱,是跨域
1.通过jsonp跨域2.通过修改document.domain来跨子域(iframe)3.隐藏的iframe+window.name跨域4.iframe+跨文档消息传递(XDM)5.跨域资源共享 C ...
- 【js跨域】js实现跨域访问的几种方式
这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据.只要协议.域名.端口有任何一个不同,都被 ...
- 【前端】【转】JS跨域问题总结
详情见原博客:详解js跨域问题 概念:只要协议.域名.端口有任何一个不同,都被当作是不同的域. 跨域资源共享(CORS) CORS(Cross-Origin Resource Sharing)跨域资源 ...
- js跨域访问,No 'Access-Control-Allow-Origin' header is present on the requested resource
js跨域访问提示错误:XMLHttpRequest cannot load http://...... No 'Access-Control-Allow-Origin' header is prese ...
- 利用JS跨域做一个简单的页面访问统计系统
其实在大部分互联网web产品中,我们通常会用百度统计或者谷歌统计分析系统,通过在程序中引入特定的JS脚本,然后便可以在这些统计系统中看到自己网站页面具体的访问情况.但是有些时候,由于一些特殊情况,我们 ...
- 三种方法实现js跨域访问
转自:http://narutolby.iteye.com/blog/1464436 javascript跨域访问是web开发者经常遇到的问题,什么是跨域,一个域上加载的脚本获取或操作另一个域上的文档 ...
- js跨域问题的解决
js提交请求给别的应用实例或者别的服务器,由于同源策略,存在js跨域的情况,我所知道两种处理方式: 1.jquery ajax+jsonp <script type="text/jav ...
随机推荐
- 使用eclipse开发hbase程序
一:在eclipse创建一个普通的java项目 二:新建一个文件夹,把hbase需要的jar放进去,我这里把hbase/lib/*.jar 下所有的jar都放进去了,最后发现就用到了下面三个jar ...
- python 迭代 及列表生成式
什么是迭代 在Python中,如果给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历我们成为迭代(Iteration). 在Python中,迭代是通过 for ...
- idea设置自定义快捷键
在说明之前,先引入一个非常好的 Intellij Idea中文教程:intelliJ Idea中文教程 一创建模板类 二使用方法备注 在IntellijIdea中我并没有找到直接对某个方法进行注释的模 ...
- 智能路由器开发指南_book
最近购得一个openwrt书籍<智能路由器开发指南>,作者张永智. Building a smart router with openwrt 作者网址:http://openwrt.bjb ...
- jQuery效果之显示与隐藏
.hide([duration][,complete])--目标元素的隐藏. .show([duration][,complete])--目标元素的显示: .toggle([duration][,co ...
- 详解Linux Top 命令
Linux top命令简介 top 命令是最流行的性能监视工具之一,我们必需了解.它是一个优秀的交互式工具,用于监视性能.它提供系统整体性能,但报告进程信息才是 top 命令的长处.top 命令交互界 ...
- Java 学习 day09
01-面向对象(内部类访问规则) package myFirstCode; /* 内部类的访问规则: 1. 内部类可以直接访问外部类的成员,包括私有private. 之所以可以直接访问外部类中的成员, ...
- PhotoKit type类型
参考链接: https://www.jianshu.com/p/42e5d2f75452/ 1.获取图像类型 enum PHAssetCollectionType : Int { case Album ...
- How to avoid Over-fitting using Regularization?
http://www.mit.edu/~9.520/scribe-notes/cl7.pdf https://en.wikipedia.org/wiki/Bayesian_interpretation ...
- 【python】-- 初识python
Python 安装 windows: 1.下载安装包 https://www.python.org/downloads/ 2.安装 默认安装路径:C:\python27 3.配置环境变量 [右键计算机 ...