当前位置: 首页 > 科技观察

Angular通过CORS实现跨域解决方案

时间:2023-03-15 10:15:44 科技观察

以前有一篇很老的文章在网上被大量转载,包括现在百度关键词“跨域”,前几条推荐是“Javascript跨域总结及解决方案”。看完觉得方法有点老了,document.domain、iframe等一些方案实在是“丑陋”,感觉已经不适用于现在的一些项目了。以iframe为例。作为一个前端工程师,我很讨厌iframe之类的东西。它不仅增加了性能上的高负载,而且也不利于控制。Angular应用中实现跨域的方式比较简单,基本上有两种方式。一种是JSONP,另一种是通过CORS。前者是比较老的方法,后者对我来说比较强大,所以这篇文章主要讲Angular和CORS如何配合跨域。如果你不使用JSONP,尽量不要使用JSONP。这是Angular跨域入手的一个原则。反正脚本的tagembedding感觉有点low。??Angular推崇当前后端分离时,哪一方实现跨域就成了问题。这就不得不说前端技术的局限性了。即使是比较好用的JSONP对于非GET请求也是无能为力的,因为它本质上是通过脚本Go获取一些资源。JSONP只能是GET的局限性,完全限制了它在Angular提倡RESTful风格接口的API场景中的使用。你不能忽略POST和PUT。而且JSONP的错误处理很弱。不满意。一般来说,前端实现跨域有各种限制,比如document.domain只能在主域相同,子域不同的情况下使用。所以综上所述,前端虽然有多种处理跨域的方式,但是很多但不够精准,缺点也比较明显。相对来说,更好的方式是通过后端参与处理,不仅适用性更强,而且前端只需要发送正常的ajax请求即可。这种技术被称为CORS.Cross-OriginResourceSharing。应该算是最值得推荐的跨域处理方案了。它不仅适用于各种方法,而且更加方便和简单。当然,这种挂东西只有现代浏览器才支持,别想IE8下的老古董了。CORS实现原理虽然通过CORS实现跨域基本都是后端实现的,但是它是一个强大的前端。你仍然需要掌握这个原则,以便当你遇到不可靠的Spectrum后端时,不......你了解CORS的本质,让服务服务端通过添加响应头Access-Control-Allow-Origin,通过HTTP实现资源共享,让每个请求的服务直接返回资源。它通过HTTP交互来判断请求源是否有资格请求资源,并通过设置HTTPHeader来控制访问资源的权限。具体过程是前端发送一个普通的请求:$http.get('www.cros.com/api/data',{params:{name:'Stubborn'}})backend:Access-Control-Allow-Origin:"*"Access-Control-Allow-Methods:"GET"Access-Control-Max-Age:"60"然后你观察浏览器的行为会发现一些有趣的东西.浏览器发现这是一个跨域请求,不需要你的干预。所以不是直接发送GET请求,而是发送OPTIONS请求,询问资源是否可以跨域访问,我们可以称这个过程为“预检”。然后我们看到OPTIONS响应返回类似如下信息:HTTP/1.1200OKDate:Mon,01Dec201301:15:39GMTServer:Apache/2.0.61(Unix)Access-Control-Allow-Origin:*Access-Control-Allow-Methods:GETAccess-Control-Max-Age:60Content-Encoding:gzipContent-Length:0Connection:Keep-AliveContent-Type:text/text这里这些Accessheaders的内容是服务器后端添加的,告诉浏览器,在此之后的60秒内,所有域都可以通过GET方法跨域访问该资源。然后浏览器自动发送真正的GET请求并返回相应的结果。请注意,此过程由浏览器自动执行。是不是很棒?部分头信息设置如下:Access-Control-Allow-Origin:|*//AuthorizationSourceControlAccess-Control-Max-Age://授权时间Access-Control-Allow-Credentials:true|false//控制是否用ajax开启cookie提交方法Access-Control-Allow-Methods:[,]*//HTTPMethodAccess-Control-Allow-Headers:[,]*//控制哪些headers可以发送真正的请求这里还有一个需要前端工程师配合的地方就是cookie的传递,通过默认情况下,cookie不会通过CORS传递。一般在header中加入cookies的做法会被浏览器拒绝并报错。上面可以看到,通过在服务器端添加响应头,Access-Control-Allow-Credentials来控制是否允许Cookie提交。在Angular中,我们需要做一些设置来达到目的:$http.post(url,{withCredentials:true,...})//或者$http({withCredentials:true,...}).post(...)//或者.config(function($httpProvider){$httpProvider.defaults.withCredentials=true;}如果是jQuery,设置如下:$.ajax("www.cros.com/api/data",{type:"GET",xhrFields:{withCredentials:true},crossDomain:true,success:function(data,status,xhr){}});描述CORS的过程,网上找了一张图:CORS分类如果仔细观察浏览器的行为,你会发现并不是所有的跨域请求都会发送OPTIONS请求,是不是有点奇怪,这里涉及到CORS的分类,简单请求和复杂请求Request.HTTP头通常包含以下内容:AcceptAccept-LanguageContent-LalanguageLast-Event-IDContent-Type的取值仅为以下之一:application/x-www-form-urlencodedmultipart/form-datatext/plainHTTPmethod为HEAD、GET、POST之一,HTTPheader包含如上所示,任何不满足这两个要求的请求都是复杂请求。比如发送PUT、DELETE等HTTP动作,或者Content-Type:application/json的内容。只有复杂的请求才会包含“preflight”Action,Access-Control-Max-Age应该也会影响OPTIONS请求的发送。原文链接:http://my.oschina.net/blogshi/blog/303758