浏览器在全局层面禁止了页面加载或执行与自身来源不同的域的任何脚本。同源策略允许页面从同一个站点加载和执行特定的脚本。浏览器通过对比每一个资源的协议、主机名和端口号来判断资源是否与页面同源。站外其他来源的脚本同页面的交互则被严格限制。跨域资源共享(Cross Origin Resource Sharing,CORS)是一个解决跨域问题的好方法,从而可以使用XHR从不同的源加载数据和资源。幸好,除CORS以外还有几个方法可以用来从外部的数据源将数据加载到应用中。我们将详细介绍其中的两种,第三种只会简要介绍(因为它需要服务器端的额外支持):
JSONP
AngularJS在$http服务中提供了一个JSONP辅助函数。通过$http服务的jsonp方法可以发送请求,如下所示:$http.jsonp("https://api.github.com?callback=JSON_CALLBACK") .success(function(data) {
//数据
});当请求被发送时,AngularJS会在DOM中生成一个如下所示的<script>标签<script src="https://api.github.com?callback=angular.callbacks._0"type="text/javascript"></script>
CORS
CORS规范简单地扩展了标准的XHR对象,以允许JavaScript发送跨域的XHR请求。它会通过预检查(preflight)来确认是否有权限向目标服务器发送请求。
预检查可以让服务器接受或拒绝来自全部服务器、特定服务器或一组服务器的请求。这意味着客户端和服务端应用需要协同工作,才能向客户端或服务器发送数据。
W3C制定CORS规范时对很多细节进行了抽象,并使其对客户端开发者透明,让开发者可以像发送同域请求一样方便地发送跨域请求。
angular.module(‘myApp‘, []) .config(function($httpProvider) { $httpProvider.defaults.useXDomain = true; delete $httpProvider.defaults.headers .common[‘X-Requested-With‘]; });
现在可以发送CORS请求了。
$http .get("https://api.github.com") .success(function(data) { // 数据 });
$http .delete("https://api.github.com/api/users/1") .success(function(data) { // 数据 });
服务器代理
实现向所有服务器发送请求的最简单方式是使用服务器端代理。这个服务器和页面处在同一个域中(或者不在同一个域中但支持CORS),做为所有远程资源的代理。
可以简单地通过使用本地服务器来代替客户端向外部资源发送请求,并将响应结果返回给客户端。通过这种方式,老式浏览器不必使用需要发送额外请求的CORS(只有现代浏览器支持CORS)也能发送跨域请求,并且可以在浏览器中采用标准的安全策略。
为了实现服务器端代理,需要架设一个本地服务器来处理我们所有的请求,并负责向第三方发送实际的请求。