以前有一篇很老的文章网上转了很多,包括现在如果你百度"跨域"这个关键字,前几个推荐的都是"Javascript跨域总结与解决方案".看了一下感觉手段有点陈旧了,有一些比如document.domain还有iframe的解决方案委实"丑陋"一些,感觉不再适用于现在一些项目中.

就拿iframe来说作为一个前端工程师,我极为讨厌iframe这种东西.它不光增加了性能上的高负荷,同时也不利于掌控.

在Angular应用中实现跨域的方式相对简单,基本上通过两种方式即可.一种是JSONP,另一种是通过CORS.前者是相对比较老的手法,后者我感觉更加给力一点,所以本文主要说一下Angular如何与CORS配合跨域.

能不使用JSONP就尽量不使用,这是着手于Angular跨域的一个原则吧.不管怎么说,script的标签嵌入感觉还是low了点.

Angular推崇的时前后端分离,所以跨域由哪一方实现成为一个问题.这个就不得不说前端技术上的局限性,即使是相对好用的JSONP对于非GET请求也是无能为力的,因为它本质上还是通过script去get一些资源.

JSONP这种只能GET的限制,在Angular推崇RESTful风格接口的API场景下,就完全制约了它的使用,总不能弃POST和PUT那些不管.并且JSONP的错误处理很弱,不尽人意.总之前端实现跨域都有各种各样的局限性,又比如像document.domain则只能用于主域相同,子域不同的情况.

所以总结而言,虽然前端有多种方式处理跨域,但是多而不精,缺点都比较明显.相对而言更好的方式是通过后端参与处理,这样做不仅适用性更强,同时前端只要发送正常的Ajax请求即可.这样的技术叫做CORS.

Cross-Origin Resource Sharing跨域资源共享,应该算是现在最为推荐的跨域处理方案.不仅适用于各种Method,而且更加方便和简单.当然了,这么吊的东西只有现代浏览器支持,IE8一下的老古董就不要想了.

CORS实现原理

虽然通过CORS实现跨域基本上完全由后端实现,不过身为一个给力的前端.还是要掌握一下这一原理,以便当你遇到不靠谱的后端时,不至于...你懂得

CORS的本质让服务器通过新增响应头Access-Control-Allow-Origin,通过HTTP方式来实现资源共享,让每个请求的服务直接返回资源.它使用了HTTP交互方式来确定请求源是否有资格请求该资源,并且通过设置HTTP Header来控制访问资源的权限.

具体的过程是这样的前端发送一个正常的请求:

$http.get('www.cros.com/api/data',{params:{

name: '顽Shi'

}})

后端设置一下response的header:

Access-Control-Allow-Origin: "*"

Access-Control-Allow-Methods: "GET"

Access-Control-Max-Age: "60"

然后你观察一下浏览器的行为会发现有趣的事,浏览器在没有你干预的情况下,发现这是一个跨域请求.所以它没有直接发送GET请求,而是发送了一个OPTIONS请求询问是否可以跨域访问该资源,这个过程我们可以称之为"预检".

然后我们看到OPTIONS的response返回了类似下面的信息:

HTTP/1.1 200 OK

Date: Mon, 01 Dec 2013 01:15:39 GMT

Server: Apache/2.0.61 (Unix)

Access-Control-Allow-Origin: *

Access-Control-Allow-Methods: GET

Access-Control-Max-Age: 60

Content-Encoding: gzip

Content-Length: 0

Connection: Keep-Alive

Content-Type: text/text

这里的这几个Access头的内容就是服务器后端加上去的,它告诉了浏览器此后的60秒内,所有域都可以通过GET方法进行跨域访问该资源.然后浏览器自动再次发送了真正的GET请求,并返回对应的结果.

注意这一过程是浏览器自动实现的,这一点是不是非常棒.一些header信息的设置如下:

Access-Control-Allow-Origin: <origin> | * // 授权的源控制

Access-Control-Max-Age: <delta-seconds> // 授权的时间

Access-Control-Allow-Credentials: true | false // 控制是否开启与Ajax的Cookie提交方式

Access-Control-Allow-Methods: <method>[, <method>]* // 允许请求的HTTP Method

Access-Control-Allow-Headers: <field-name>[, <field-name>]* // 控制哪些header能发送真正的请求

这里还有一处需要前端工程师协作的地方就是cookie的传递,默认情况下通过CORS这样的方式是不会传递cookie.一般强制性将cookie添加到header的做法,也会被浏览器拒绝并报错.上面看到了在服务器端会通过添加一个response头,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的分类,简单请求和复杂请求.

HTTP的header通常包含下面这些内容:

Accept

Accept-Language

Content-Language

Last-Event-ID

Content-Type的值仅是下列之一:

application/x-www-form-urlencoded

multipart/form-data

text/plain

HTTP方法是HEAD,GET,POST之一,同时HTTP的header包含如上面所示.任何一个不满足这两种要求的请求,都是复杂请求.比如发送PUT,DELETE等HTTP动作,或者Content-Type: application/json的内容.

只有复杂请求包含"预检"这一动作,另外Access-Control-Max-Age应该也会影响OPTIONS请求的发送.

Angular通过CORS实现跨域方案的更多相关文章

  1. SpringMvc+AngularJS通过CORS实现跨域方案

    什么是跨域请求问题? 这个问题的起因在于现代浏览器默认都会基于安全原因而阻止跨域的ajax请求,这是现代浏览器中必备的功能,但是往往给开发带来不便. 但跨域的需求却一直都在,为了跨域,勤劳勇敢的程序猿 ...

  2. springboot基于CORS处理跨域问题

    1. 为什么有跨域问题 跨域不一定都会有跨域问题. 因为跨域问题是浏览器对于ajax请求的一种安全限制:一个页面发起的ajax请求,只能是与当前页域名相同的路径,这能有效的阻止跨站攻击. 因此:跨域问 ...

  3. 14 微服务电商【黑马乐优商城】:day06-使用nginx反向代理并掌握cors解决跨域

    本项目的笔记和资料的Download,请点击这一句话自行获取. day01-springboot(理论篇) :day01-springboot(实践篇) day02-springcloud(理论篇一) ...

  4. 403 Invalid CORS request 跨域问题

    5.跨域问题 跨域:浏览器对于javascript的同源策略的限制 . 以下情况都属于跨域: 跨域原因说明 示例 域名不同 www.jd.com 与 www.taobao.com 域名相同,端口不同 ...

  5. 403 Invalid CORS request 跨域问题 invalid+cors+request什么意思

    5.跨域问题 跨域:浏览器对于javascript的同源策略的限制 . 以下情况都属于跨域: 跨域原因说明 示例 域名不同 www.jd.com 与 www.taobao.com 域名相同,端口不同 ...

  6. 配置CORS解决跨域调用—反思思考问题的方式

    导读:最近都在用一套完整的Java EE的体系做系统,之前都是用spring框架,现在弄这个Java EE,觉得新鲜又刺激.但,由于之前没有过多的研究和使用,在应用的过程中,也出现了不少的问题.累积了 ...

  7. angularjs简单实现$http.post(CORS)跨域及$http.post传参方式模拟jQuery.post

    1.开启angularjs的CORS支持 .config(function($httpProvider) { // CORS post跨域配置 $httpProvider.defaults.useXD ...

  8. 前端总结·基础篇·JS(四)异步请求及跨域方案

    前端总结系列 前端总结·基础篇·CSS(一)布局 前端总结·基础篇·CSS(二)视觉 前端总结·基础篇·CSS(三)补充 前端总结·基础篇·JS(一)原型.原型链.构造函数和字符串(String) 前 ...

  9. Spring Boot中通过CORS解决跨域问题

    今天和小伙伴们来聊一聊通过CORS解决跨域问题. 同源策略 很多人对跨域有一种误解,以为这是前端的事,和后端没关系,其实不是这样的,说到跨域,就不得不说说浏览器的同源策略. 同源策略是由Netscap ...

随机推荐

  1. 利用ipython实现多线程

    多线程来批量化处理数据的时候希望简单的应用,使用ipython会很简单 参考这里

  2. 创建好Android Application Project 后运行就报错。

    如图: 这个问题有可能是有可能是没导入Android support库,简单了解一下: google提供了Android Support Library package 系列的包来保证来高版本sdk开 ...

  3. jquery 使用需要注意

    jquery选择器,层选择器等多个选择器,jquery生成对象,jquery遍历对象, jquery ajax调用不要进行方法封装返回值方式调用,会取不到值. jquery使用要注意很多细节点才能将其 ...

  4. PRML读书后记(一): 拟合学习

    高斯分布·拟合 1.1 优美的高斯分布 中心极限定理[P79]证明均匀分布和二项分布在数据量 $N\rightarrow \infty$ 时,都会演化近似为高斯分布. 作为最晚发现的概率分布,可以假设 ...

  5. [BZOJ3139][HNOI2013] 比赛

    Description 沫沫非常喜欢看足球赛,但因为沉迷于射箭游戏,错过了最近的一次足球联赛.此次联 赛共N支球队参加,比赛规则如下:  (1) 每两支球队之间踢一场比赛. (2) 若平局,两支球队各 ...

  6. ZooKeeper学习总结 第二篇:ZooKeeper深入探讨(转载)

    其实zookeeper系列的学习总结很早就写完了,这段时间在准备找工作的事情,就一直没有更新了.下边给大家送上,文中如有不恰当的地方,欢迎给予指证,不胜感谢!. 1. 数据模型 1.1. 只适合存储小 ...

  7. Java的序列化ID的作用

    Java的序列化ID的作用 简单来说,Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的.在进行反序列化时,JVM会把传来的字节流中的serialVersio ...

  8. FileOutputStream和FileInputStream的用法

    public static void show() { File f=new File("d:"+File.separator+"1.txt"); FileOu ...

  9. FP error code老是忘记的看这里:只给出最常用的几个。

    把常见的几个记牢,不要在比赛时纠结. 错误2:输入文件未找到. 错误106:数据读入的格式错误,往往是读入语句出错. 错误200:被零除. 错误201:范围检查错误,数组越界. 错误202:栈溢出. ...

  10. Model & ModelMap & ModelAndView 比较ModelFactory简介

    Model: 是一个接口,其实现类必继承ModelMap. ModelMap: 继承与LinkedHashMap,相当于自定义了一个map. ModelAndView: 里面封装了两个对象,其中vie ...