现在越来越多的项目就算是一个管理后端也偏向于使用前后端分离的部署方式去做,为了顺应时代的潮流,一前后端分离就产生了跨域问题,所以许多同学把跨域和前后端分离项目联系在了一起,其实跨域产生的原因并不是前后端分离导致的,那我们一起来看一下,希望可以靠这一篇文章解答大家所有的跨域问题
一、跨域产生的条件
-
<李>使用xmlHttpRequest,即我们通常说的ajax请求李>
<李>浏览器做了这个事李>
<李>访问的域名不同,即访问的html页面是一个域名下的,但内部js发送的ajax请求的目标地址却是b域名李>
以上三个条件缺一不可,尤其是第三个条件许多做移动端的同学可能都没有听过,因为移动端爽爽的用各种http请求狂发不同的域名,但是浏览器不允许我们这么做,为了一个词<强>安全强>
二,如何解决跨域问题
解决跨域问题的根本就是要打破上述的三个限制中的任何一个,我们来看一下逐个击破的方式
JSONP方式
jsonp是打破第一重限制,用了XMLHttpRequest就跨域,那我不用这种方式了,我们怎么做的,来看一段jquery的带jsonp的ajax请求
<代码> . ajax({美元 类型:“获得”, url:“http://api.map.baidu.com/geocoder/v2/? 数据:“地址=上海”, 数据类型:“jsonp”, jsonp:“回调”, jsonpCallback:“showLocation”, 成功:功能(数据){ alert("成功”); }, 错误:功能(数据){ alert("失败”); } });代码>
看似用了ajax请求,其实内部完全不是那么回事,多了jsonp和jsonpCallback选项,它内部将代码翻译并把页面上的dom操作成这样
<代码> & lt; !DOCTYPE html> & lt; html> & lt; head> & lt;元charset=皍tf - 8”比; & lt;/head> & lt; body> & lt; script type=' text/javascript '比;//后端返回直接执行的方法,相当于执行这个方法,由于后端把返回的数据放在方法的参数里,所以这里能拿到res。 窗口。showLocation=函数(res) { console.log (res)//执行ajax回调 } & lt;/script> & lt;脚本src=" http://api.map.baidu.com/geocoder/v2/?address=上海,回调=showLocation ' type=' text/javascript '祝辞& lt;/script> & lt;/body> & lt;/html> 代码>
这个时候,html页面src的脚本标签回去访问api.map.baidu.com的服务端,由于脚本,img这种标签浏览器是不受xmlhttprequest限制的,可以随意访问,这个时候对应的后端代码取得地址参数,最后根据双方约定好的调参数,返回一个被包装后的json,即
<代码> showLocation ({ 状态:0, 结果:{ 地点:{ 液化天然气:121.4219317908279, 纬度:31.361653367912695 }, 精确:1、 信心:80年, 理解:99, 级别:“道路” } })代码>
然后浏览器直接执行了对应的这个showLocation()…等等,这个不就相当于执行了我们上面定义的窗口。showLocation方法并且传入了我们需要的json返回吗,那我们成功的ajax方法里就可以得到这个返回类型了,并且没有跨域,是不是很精妙。
歌珥
歌珥是一个W3C标准,全称是“跨域资源共享“(跨源资源共享)跨域资源共享歌珥详解。这个玩样用于“破”解掉浏览器的限制,说是破解其实也是浏览器认识到了一些头部就放行了的意思,需要在http的响应内多设置几个头部
-
<李> <>强Access-Control-Allow-Origin 强>:*表明允许所有的起源(浏览器的html页面路径)访问,而并非是同源的起源李>
<李> <>强Access-Control-Request-Method 强>:*表明允许所有的http请求头,访问,因为浏览器在触发如下几个场景会在发送真正的数据前发送选项这样的预检请求检测,一旦预检通过后才会发送真正的get或post数据请求,这个时候我们按照歌珥的设置就需要允许对应的方法访问,触发的几种情况包括
1:请求的方法不是get/头/post
2:帖子请求的内容类型并非应用程序/x-www-form-urlencoded,多部分/格式,或文本/纯
3:请求设置了自定义的头字段等李> <李> <>强Access-Control-Allow-Headers 强>:*设置所有头均可以被允许,这个配置联通上述的请求方法选择检测一起使用,可以在需要自定义头的场景下使用李>