HTML5技术

ajax跨子域请求的两种现代方法 - zhjh256

字号+ 作者:H5之家 来源:H5之家 2016-09-07 13:00 我要评论( )

因为面向互联网的性质,我们公司的大部分系统都采用多子域的方式进行开发和部署,以达到松耦合和分布式的目的,因此子系统间的交互不可避免。虽然通过后台的rpc框架解决了大部分的交互问题,但有些情况下,前端直接发起的各子系统之间交互仍然不可避免。由于

因为面向互联网的性质,我们公司的大部分系统都采用多子域的方式进行开发和部署,以达到松耦合和分布式的目的,因此子系统间的交互不可避免。虽然通过后台的rpc框架解决了大部分的交互问题,但有些情况下,前端直接发起的各子系统之间交互仍然不可避免。由于浏览器天然的安全性本质,早期通常是不允许直接调用不同域名下的请求。如果直接调用不同域下的请求,会报“No 'Access-Control-Allow-Origin' header is present on the requested resource”错误。

所以在HTML 5以前,都是变相的方式绕过,主要有如下几种方式:

JSONP

我们发现,Web页面上调用js文件时不受是否跨域的影响,凡是拥有"src"这个属性的标签都拥有跨域的能力,比如<script>、<img>、<iframe>。那就是说如果要跨域访问数据,就服务端只能把数据放在js格式的文件里。恰巧我们知道JSON可以简洁的描述复杂数据,而且JSON还被js原生支持,所以在客户端几乎可以随心所欲的处理这种格式的数据。然后客户端就可以通过与调用脚本一模一样的方式,来调用跨域服务器上动态生成的js格式文件。客户端在对JSON文件调用成功之后,也就获得了自己所需的数据。这就形成了JSONP的基本概念。允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。

在angularjs中,通常是如下:

$http.jsonp(url + "?callback=JSON_CALLBACK") .success(function(data) {
 将data赋值给$scope的某些属性
});

但JSONP只支持get,这样就限制了传递的数据量。所以就有了HTML 5里面的CORS。

CORS

Cross-Origin Resource Sharing (CORS) 是W3c工作草案,它定义了在跨域访问资源时浏览器和服务器之间如何通信。CORS背后的基本思想是使用自定义的HTTP头部允许浏览器和服务器相互了解对方,从而决定请求或响应成功与否。CORS规范简单地扩展了标准的XHR对象,以允许JavaScript发送跨域的XHR请求。它会通过
预检查(preflight)来确认是否有权限向目标服务器发送请求。

CORS与JSONP相比,更为先进、方便和可靠。

1、 JSONP只能实现GET请求,而CORS支持所有类型的HTTP请求。
2、 使用CORS,开发者可以使用普通的XMLHttpRequest发起请求和获得数据,比起JSONP有更好的错误处理。
3、 JSONP主要被老的浏览器支持,它们往往不支持CORS,而绝大多数现代浏览器都已经支持了CORS。如下:


对一个简单的请求,没有自定义头部,要么使用GET,要么使用POST,它的主体是text/plain,请求用一个名叫Orgin的额外的头部发送。Origin头部包含请求页面的头部(协议,域名,端口),这样服务器可以很容易的决定它是否应该提供响应。
服务器端对于CORS的支持,主要就是通过设置Access-Control-Allow-Origin来进行的。
Header set Access-Control-Allow-Origin * 
为了防止XSS攻击我们的服务器, 我们可以限制域,比如在nginx中可以如下设置:

http {
......
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Headers X-Requested-With;
add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
......
}

具体参见https://michielkalkman.com/snippets/nginx-cors-open-configuration.html

在angularjs中,我们可以如下调用cors请求:

myApp.config(function($httpProvider) {
$httpProvider.defaults.useXDomain = true;
});
myApp.controller("JsonController",function($scope,$http) {
$scope.getAjax = function(url) {
$http.get(url).success(function (response) {
$scope.students = response;
});
};
});

 

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • 如何独立开发一个网络请求框架 - 指尖下的幽灵

    如何独立开发一个网络请求框架 - 指尖下的幽灵

    2016-08-15 11:00

  • 史上最全ajax全套 - 张岩林

    史上最全ajax全套 - 张岩林

    2016-08-06 12:00

  • Vue.js基于$.ajax实现数据的跨域增删查改 - keepfool

    Vue.js基于$.ajax实现数据的跨域增删查改 - keepfool

    2016-07-09 11:17

  • ajax对一些没有接口的数据进行分析和添加方法 - 小小年128

    ajax对一些没有接口的数据进行分析和添加方法 - 小小年128

    2016-05-21 13:00

网友点评
r