什么是跨域
跨域是 指从一个域名的网页去请求另一个域名的资源 。比如从www.baidu.com 页面去请求 www.google.com
的资源。跨域的严格一点的定义是:只要 协议,域名,端口有任何一个的不同,就被当作是跨域
为什么浏览器要限制跨域访问呢?
原因就是安全问题:如果一个网页可以随意地访问另外一个网站的资源,那么就有可能在客户完全不知情的情况下出现安全问题。比如下面的操作就有安全问题:
用户访问www.mybank.com ,登陆并进行网银操作,这时cookie啥的都生成并存放在浏览器
用户突然想起件事,并迷迷糊糊地访问了一个邪恶的网站 www.xiee.com
这时该网站就可以在它的页面中,拿到 银行的cookie ,比如用 户名,登陆token等 ,然后发起对www.mybank.com 的操作。
如果这时浏览器不予限制,并且银行也没有做响应的安全处理的话,那么用户的信息有可能就这么泄露了。
为什么要跨域
既然有安全问题,那为什么又要跨域呢? 有时公司内部有多个不同的子域,比如一个是location.company.com
,而应用是放在app.company.com , 这时想 从 app.company.com去访问 location.company.com
的资源就属于跨域 。
跨域访问需要的两件宝贝
由于浏览器一般不对script,img等进行跨域限制,所以我们有机会通过script的方式来实现跨域访问。
跨域访问需要用到两样东东,一个是JSON,一种基于文本的传输协议; 一种是JSONP,一群码农想出来的跨域解决方案
。关于JSON与JSONP的解释,可以参考 JSON & JSONP
实现跨域访问 服务端需要做什么
服务端要检查访问的请求参数,如果没有callback,则可以按照之前的流程走;如果
带着callback参数,则需要将返回的结果包装在callback里面。
比如请求的URL是: app.company.com/location?callback=myCallback , 那么服务端则需要
把结果封装进myCallback 函数里面 , 如下
1 | if (params.query && params.query.callback) { |
实现跨域访问 客户端需要做什么
客户端有多种方式可以实现JSONP的调用:
jQuery
jQuery可以在Ajax里面设置datatype为jsonp,则可以进行跨域访问
1 | $scope.jqueryJsonpRequest = function(){ |
AngularJS
AngularJS的$http 也提供了对jsonp的访问,直接调用jsonp进行跨域访问
1 | $http.jsonp('https://public- |
手动实现
不管是jQuery也好,AngularJS也罢,底下都不是发起XHR (XML HTTP
Request),而都是通过加载javascript的方式来做的,所以如果项目没有依赖jQuery或者AngularJS,则可以自己手动实现jsonp的调用。
原理很简单,就是用javascript动态加载一个script文件,同时定义一个callback函数给script执行而已。
1 | //定义callback 函数 |