工作中总是遇到跨域问题,但是常常遇到了也不知道这是跨域导致的问题,或者知道了也还是不知道怎么解决。于是,就找了各方资料作了以下分享。
首先,跨域的发生只是因为浏览器拦截了xhr的跨域请求,不让我们拿到后台数据的是浏览器而不是后台。
细分下来,三个原因就是:
一、浏览器的限制
二、这是个xhr请求
三、跨域
同时满足这三个才会出现跨域问题。
那么,针对这三个问题我们来一一击破,就可以解决跨域问题了。
一、修改浏览器的跨域设置
比较常用的是chrome浏览器,其跨域设置很简单。
右击chrome图标——在属性页面中的目标输入框里加上 --disable-web-security 如下图所示:
重新打开chrome浏览器,如果浏览器头部出现这行字说明配置成功啦,如图:
但是问题来了,不能要求所有用户的浏览器都配置成可跨域吧
二、把xhr请求,换成别的请求
1、 换成jsonp请求
jsonp是json padding,就是json的补充使用,不是json的官方协议但是也是一个补充约定。
到底是啥,简单来说就是前端发送一个jsonp的请求(请求中加一个dataType字段,值为jsonp)。
这个请求就变成了jsonp请求了。那么请求的这个接口就变成了这样:
是下面那个绿色的哦(上面那个是非jsonp请求,做个对比)。一个是请求的type已经不是xhr了,而是script了(所以已经不构成跨域问题了),还有一个区别是请求里面多了callback参数。同时,后台也要配置成可接受jsonp请求。为啥要配置,因为前端请求type变成了script了,前端需要的是js代码所以后台再返回 json字符串的话前端肯定要报错了。
配置成这样了之后,后台就会把原来的json 外面包一层 函数,它就变成一个可调用函数的js代码了。
共同点是都有“callback”啊。没错,callback就是他们定的约定:如果前端请求时候加了callback参数,后台收到了就会自动把要返回的json对象转化为scrip标签的js函数。(这个script标签我们在开发者模式里找不到,因为他默认是动态创建的,调用完了会自动销毁,要想缓存也可以在后台代码中额外配置的)。
但是,Jsonp只支持get方法,而且它的请求方式不是xhr,意味着xhr它的异步、属性都不能使用,不方便啊。所以jsonp还是很少用的。
三、跨域解决,根本方法CORS
CORS是跨源资源分享(Cross-Origin Resource Sharing)的缩写。它是W3C标准,是跨源AJAX请求的根本解决方法。相比JSONP只能发GET请求,CORS允许任何类型的请求。
CORS请求分为简单请求和非简单请求。
借鉴慕课网上大神以为大神根据个人经验总结的结果:
1、 简单请求对于简单请求,浏览器直接发出CORS请求。就是浏览器发现这次跨源AJAX请求是简单请求,就自动在请求头中,添加一个Origin字段(只要跨域了,非简单请求也会有这个字段)。如下:
Origin字段用来说明,本次请求来自哪个源(协议 + 域名 + 端口)。服务器根据这个值,决定是否同意这次请求。可设置为 * ,表示可匹配所有域。
对应的,浏览器会识别响应头中Access-Control-Allow-Origin字段,看和请求头的origin值是否匹配。匹配了才允许其跨域访问。响应头的字段可以让后端人配。
对应上文的请求头,响应头应该是Access-Control-Allow-Origin: http://localhost:8081
除此之外,还有:
Access-Control-Allow-Credentials表示在发送请求时是否允许带上cookie,这里不仅要服务器同意,并且我们在ajax请求中也要打开withCredentials属性。
关于cookie: 需要注意的是,如果要发送Cookie,Access-Control-Allow-Origin就不能设为星号,必须指定明确的、与请求网页一致的域名。
2、 非简单请求
非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUT或DELETE,或者Content-Type字段的类型是application/json。
浏览器对简单和非简单请求的处理方式完全不一样。一样简单请求会直接请求,然后在判断请求头和响应头是否匹配。而非简单请求,他会先执行一个“预检命令”先判断请求头和响应头是否对应匹配,匹配成功后才会去请求真正的那个接口,否则就报错了不会进行下一步请求。
后台要配置对象的响应头:
代理配置:
Nginx和apatch配置。(这也是我们工作中常用的一种方法,其原理和CORS方法类似,一般需要找运维配nginx,具体配置方法就没深入研究了)
部分摘自:
浏览器同源政策及其规避方法 作者:阮一峰
http://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html
作者:安静de沉淀