前言从我第一次接触前端开发开始,跨域这个词就一直在我身边高频率的重复着。到现在调试了N个跨域Domain相关的问题,2016年也整理了一篇相关的文章,但还是觉得少了点什么,所以现在重新整理一下。个人知识有限,如有错误,还请见谅,欢迎提issue,看到此标题,请勿喷~标题是关于跨域的,有N种,本文只针对ajax请求跨-domain(,ajax跨域只是浏览器“同源策略”的一部分。其他还有Cookie跨域iframe跨域,LocalStorage跨域等,这里不再介绍),以及内容大致如下:什么是ajax跨域性能(整理了一些遇到的问题及解决方法)如何解决ajax跨域JSONP方法CORS方法代理请求方法如何解析ajax跨域HTTP包captureSomeexamplesajax跨域的原理是什么ajax跨域ajax请求跨域错误,主要是因为浏览器的“同源策略”,可以参考浏览器的同源策略及其规避方法(YifengRuan)CORS请求st原理CORS是一个W3C标准,全称是“跨源资源共享”(Cross-originresourcesharing))。它允许浏览器向跨域服务器发送XMLHttpRequest请求,从而克服AJAX只能在同源上使用的限制。目前基本上所有的浏览器都实现了CORS标准。事实上,几乎所有的浏览器ajax请求都是基于CORS机制的,但是前端开发者可能并不关心(所以其实目前CORS的解决方案主要是考虑后台如何实现的问题)。关于CORS,强烈推荐阅读CORS跨域资源共享详解(阮一峰)。另外,这里还有一个实现示意图(简化版):如何判断是不是简单请求?浏览器将CORS请求分为两类:简单请求(simplerequest)和非简单请求(not-so-simplerequest)。只要同时满足以下两个条件,就是一个简单的请求。请求方式为以下三种方式之一:HEAD、GET、POSTHTTP头信息不超过以下字段:AcceptAccept-LanguageContent-LanguageLast-Event-IDContent-Type(限于三个值application/x-www-form-urlencoded,multipart/form-data,text/plain)如果以上两个条件没有同时满足,则为非简单请求。Ajax跨域性能说实话,一开始我整理了一篇文章,然后作为解决方案,后来发现还有很多人还是不会。无奈只能费时费力调试。但是,即使我分析了,我也只会根据相应的性能来判断是否跨域,所以这个很重要。ajax请求时,如果出现跨域现象,又不解决,会有如下表现:(注意是ajax请求,请不要说为什么http请求可以,ajax不行,因为ajax是伴随着跨域的,所以只要http请求可以就不行)注:具体的后端跨域配置可以参考题目所在位置。第一种现象:请求的资源没有'Access-Control-Allow-Origin'头,并且响应有HTTP状态码404出现这种情况的原因如下:这个ajax请求是一个“非简单请求”,所以在请求之前会发送一个预检请求(OPTIONS)。服务器端后台接口不允许OPTIONS请求,导致找不到对应的接口地址。解决方案:后端允许选项请求。第二种现象:请求的资源上没有'Access-Control-Allow-Origin'标头,并且响应具有HTTP状态码405与第一个不同。这种情况下,后台方法是允许OPTIONS请求的,但是在某些配置文件(比如安全配置)中,OPTIONS请求被屏蔽了,导致出现这种现象。解决方法:后台关闭相应的安全配置。现象三:请求的资源没有'Access-Control-Allow-Origin'header,status200同第一种和第二种不同。这种情况下,服务器端后台允许OPTIONS请求,接口也允许OPTIONS请求,但是匹配header时出现不匹配,比如originheader校验不匹配,比如缺少对某些headers的支持(比如常见的X-Requested-Withheader),然后服务器会把response返回给前端。前端检测到后,会触发XHR.onerror,导致前端控制台报错。解决方法:后端添加相应的header来支持第四种现象:headercontainsmultiplevalues'*,*'现象是后台响应的http头信息有两个Access-Control-Allow-Origin:*到老实说,出现这种问题主要是做跨域配置的人不懂原理,导致重复配置,比如:常见于.net后台(一般在web.config配置origin一次,然后在代码中手动添加一次origin(如代码中Manuallysetreturns*)).net后台常见(在IIS和项目webconfig中同时设置Origin:*)解决方法(一一对应):建议删除代码中手动添加的*,只使用项目配置.建议删除IIS*下的配置,直接使用项目配置解决ajax跨域。一般ajax跨域的解决方案都是通过JSONP或者CORS来解决的,如下:(注意现在几乎不用JSONP了,可以理解JSONP。)JSONP解决跨域问题的方法jsonp解决跨域问题是比较老的方案(实践中不推荐),这里简单介绍一下(如果在实际项目中要使用JSONP,一般会使用JQ等封装JSONP类库来进行ajax请求)实现原理原因为什么JSONP可以用来解决跨域的解决方案,主要是因为元素向服务端请求JSON数据,不受同源策略限制functionaddScriptTag(src){varscript=document.createElement('script');script.setAttribute("type","text/javascript");script.src=src;document.body.appendChild(script);}window.onload=function(){addScriptTag('http://example.com/ip?callback=foo');}functionfoo(data){console.log('responsedata:'+JSON.stringify(data));};请求时,将接口地址作为构造脚本标签的src,这样构造脚本标签时,最终的src就是接口返回的内容。server对应的接口在返回参数foo({"test":"testData"})外增加了一个函数包装层因为
