引起跨域的原因:

1、浏览器限制;

2、跨域(协议、域名,端口不一样都是跨域,即违反同源策略);

3、XHR(XMLHttpRequest请求);

同时满足以上三个条件就会产生跨域。

解决跨域的方法:

1.禁止浏览器做检查校验

在浏览器属性里加上 --disable-web-security --user-data-dir

2.jsonp

不是一个官方协议,是利用script标签请求可以跨域来解决跨域问题(带url/href的标签都不会受同源策略的影响,eg:link、img、script等)。这个script创建完使用完就销毁了,html里不可见(可以通过对jq源码打断点去查看,大概在9800行)

jsonp的实现原理是:请求类型为script来避开跨域,前后台约定带有“callback”这个参数的请求就是jsonp请求,前台发出去的请求加了“callback”参数,当后台发现请求中带“callback”时,后台就知道这是一个jsonp请求,就会把返回的数据由json变成JS代码返回,JS代码内容就是一个函数的调用,函数名是“callback”参数的值,而原来需要返回的json对象数据在这里作为参数传递返回。后面的“_”表示不缓存。

ajax跨域javacors南汽 ajax 跨域_ajax跨域javacors南汽

缺点:

  • 服务器需要改动代码支持(因为服务器正常会返回json数据,而浏览器会以解析js的方式去解析服务器返回的数据,那么结果就会报错)
  • 只支持GET方法,JSONP是通过动态创建一个script发送请求的,而script只支持GET方法

3.CORS

CROS重点就在服务器上,只要配置了允许CROS,就可以正常发送请求,非常方便且安全性好,具体的服务器配置取决于服务端的不同实现。

浏览器发现请求是跨域的时候,会在请求头上加上origin: 域名,当请求返回时,就会检查响应头里面有没有允许跨域的信息,没有的话就报错。

那么我们只要在服务器上加上如下代码即可:

res.addHeader("Access-Control-Allow-Origin ", "http://localhost:8081");//*代表所有域

Access-Control-Allow-Methods,"get" //*代表所有方法

复杂请求

当浏览器要发送跨域请求时,如果是简单请求,就是先执行后判断,如果是复杂请求,浏览器会先发送一个options预检命令即一个options请求,当该请求通过时才会再发送真正的请求。如下,发送两个请求

ajax跨域javacors南汽 ajax 跨域_ajax跨域javacors南汽_02

该option请求会根据请求的信息去询问服务端支不支持该请求。比如发送的数据是json类型(通过content-type设置)的话,会携带一个请求头Access-Control-Request-Headers: content-type去询问支不支持该数据类型,如果支持(res.addHeader("Access-Control-Allow-Headers ", "Content-Type")),则请求就会通过,并发送真正的请求

可以通过将预检命令缓存来减少请求

设置方法是服务端响应头设置Access-Control-Max-Age,值是缓存时间

ajax跨域javacors南汽 ajax 跨域_服务器_03

 

带cookie的跨域(发送的cookie只能是被调用方的cookie,而不是调用方的cookie)

前面设置响应头Access-Control-Allow-Origin: *,可以解决跨域,但是在带cookie的跨域请求中就不能试用了,origin必须是全匹配,而之前说了请求头里面会带有origin,那我们把这个值获取下,就可以做完全匹配了。此外带cookie的跨域还需要在响应头中设置Access-Control-Allow-Credentials的值为true

4.服务器代理

调用方修改Apache或者Nginx静态服务器,通过静态服务器隐藏调用请求返回给浏览器,在浏览器视角来看,还是同源访问,自然也就不存在跨域的问题了。

-----

其他方案:document.domain、window.name、location.hash、postMessage、websocket协议等(先记录下~~~)