在日常的项目开发时会不可避免的需要进行跨域操作,面试中也是频繁被经常会问到的问题,本文只是我经常用到的解决跨域的方式做个记录与总结。
所有支持Javascript的 浏览器 都会使用‘同源策略’这个安全策略,所谓同源是指,域名,协议,端口相同,就是因为同源策略的影响导致没法直接用XMLHttpRequest请求不同域上的数据,所以各种解决问题的技术出现了。
Jsonp
<script> 标签元素是不受同源策略影响,OK,利用这一个漏洞,可以实现加载不同域服务器上的脚本啦。该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。
以jquery封装的$.getJson()为例:
<script type="text/javascript">
$.ajax({
type: "get",
url: "http://www.test.com?name='test'",
dataType: "jsonp",
jsonpCallback:"callbackFun",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以写"?",jQuery会自动为你处理数据
success: function(json){
alert('success');
},
error: function(){
alert('fail');
}
});
});
</script>
通过dataType指定jsonp,jquery底层封装后,会在head标签后面追加<script src="http://www.test.com?name='test'&callback=callbackFun"></script>
所有的jsonP都是这个原理,借助script标签的跨域特性来实现,callbackFun再jquery中是自动生成的,后台会获取jsoncallback参数,获取对应的函数名称,最后包装成想要的格式,比如最后输出结果是:callbackFun({"result":"suc","code":"1000"}),那么再Jquery中,会将该方法直接指定给success方法,最后来接收返回的数据。
JSONP的优点是:它不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制;它的兼容性更好,在更加古老的浏览器中都可以运行,不需要XMLHttpRequest或ActiveX的支持;并且在请求完毕后可以通过调用callback的方式回传结果。
JSONP的缺点则是:它只支持GET请求而不支持POST等其它类型的HTTP请求;它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题。
cors
CROS(Cross-Origin Resource Sharing)跨域资源共享,定义了必须在访问跨域资源时,浏览器与服务器应该如何沟通。CROS背后的基本思想就是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功还是失败。CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。
前端实现方式和一般的ajax请求是一样的,只是方式的接口是绝对地址。服务器端对于CORS的支持,主要就是通过设置Access-Control-Allow-Origin来进行的。如果浏览器检测到相应的设置,就可以允许Ajax进行跨域的访问。
JSONP只支持GET请求,CORS支持所有类型的HTTP请求。JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。
服务器代理
禁止跨域问题其实是浏览器的一种安全行为,假如我们的目标服务器不能设置header,而且我们需要发送post请求,上面的解决方案就被否定了,但是服务器与服务器之间的请求是不存在跨域的。
强大的nginx,伟大的nodeJS都可以实现一个代理服务器功能。
反向代理服务器,就是把http请求转发到另一个或者一些服务器上。通过把本地一个url前缀映射到要跨域访问的web服务器上,就可以实现跨域访问。对于浏览器来说,访问的就是同源服务器上的一个url。而nginx通过检测url前缀,把http请求转发到后面真实的物理服务器。并通过rewrite命令把前缀再去掉。这样真实的服务器就可以正确处理请求,并且并不知道这个请求是来自代理服务器的。
nginx的配置方法网上已经泛滥了,保存几个参考过的网址。
http://www.imooc.com/article/...
http://www.cnblogs.com/renjin...
http://www.cnblogs.com/bninp/...
nodeJs 主要是使用的node-http-proxy实现的,相关信息也很多。
https://github.com/nodejitsu/...
http://www.cnblogs.com/woodk/...
http://blog.csdn.net/jaye100/...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。