如何克服ajax跨域

背景

 最近做项目经常碰到跨域的问题,总在联调中浪费了不少时间,当然若时间充裕的话,跨域基本都是可以通jsonp来解决问题(get方式的请求),只是因为对接环境问题,就打算在请求头设置参数来解决跨域问题。

跨域资源共享 CORS 原理

 CORS定义一种跨域访问的机制,可以让AJAX实现跨域访问。CORS 允许一个域上的网络应用向另一个域提交跨域 AJAX 请求。实现此功能非常简单,只需由服务器发送一个响应标头即可。这种方案也是我们最长用的,也是比较简单的。

例子如下:

JAVA后端代码:

response.setHeader("Access-Control-Allow-Origin", "http://www.xxx.com");

response.setHeader("Access-Control-Allow-Credentials", "true");

(1)Access-Control-Allow-Origin

表示接受任意域名的请求,如果是多个域名中间用','隔开,如果是 * 表示允许任何域名

(2)Access-Control-Allow-Credentials

该字段可选。它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可。

(3)Access-Control-Expose-Headers

该字段可选。CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。上面的例子指定,getResponseHeader('FooBar')可以返回FooBar字段的值

(4)Access-Control-Allow-Credentials

CORS请求默认不发送Cookie和HTTP认证信息。如果要把Cookie发到服务器,一方面要服务器同意,指定Access-Control-Allow-Credentials字段。另外发送请求方需要varxhr=newXMLHttpRequest();   xhr.withCredentials=true; 否则,即使服务器同意发送Cookie,浏览器也不会发送。或者,服务器要求设置Cookie,浏览器也不会处理。但是,如果省略withCredentials设置,有的浏览器还是会一起发送Cookie。这时,可以显式关闭withCredentials。

然而我们经常设置这样的选项,还是会在浏览器弹出:XMLHttpRequest cannot load http:/www.xxx.com.Origin http://api.bob.com is not allowed by Access-Control-Allow-Origin. 这样的字眼,而且在post请求复现高。

这个时候多是因为浏览器发送了有一个预检请求,"预检"请求用的请求方法是OPTIONS,表示这个请求是用来询问的。头信息里面,关键字段是Origin,表示请求来自哪个源。

在预检请求会带两个参数

(1)Access-Control-Request-Method

该字段是必须的,用来列出浏览器的CORS请求会用到哪些HTTP方法,上例是PUT。

(2)Access-Control-Request-Headers

该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段

服务器收到"预检"请求以后,检查了Origin、Access-Control-Request-Method和Access-Control-Request-Headers字段以后,确认允许跨源请求,就可以做出回应。

所以如果是post的请求获取其他非简单的请求的话,我们可以尝试在请求头中加上

response.setHeader(Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");(注意,返回的是所有支持的方法,而不单是浏览器请求的那个方法。这是为了避免多次"预检"请求。)

res.setHeader("Access-Control-Allow-Headers", "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,userId,token");

就能解决上述的即使加了请求头允许跨域的域名以及Cookie的身份验证,依旧出现跨域的问题。

由于CORS请求和浏览器有关,所以在低版本IE或者其他的流量器如果不支持,该方式是行不通的,这个时候就只能使用JsonP的方式来解决跨域。

JSONP解决跨域原理

JSONP(JSON with Padding)是JSON的一种”使用模式”,可用于解决主流浏览器的跨域数据访问的问题。由于同源策略,一般来说位于 server1.example.com 的网页无法与不是 server1.example.com的服务器沟通,而 HTML 的script元素是一个例外。利用 标签

你可能感兴趣的:(如何克服ajax跨域)