CORS跨域问题

跨域的分类

1. 域名不同

2. 域名相同,端口不同

3. 二级域名不同

引入跨域限制的原因

处于安全考虑。例如,浏览淘宝的时候访问了这个网站,这个网站利用ajax可能访问淘宝进行操作,这时候会拿着你的淘宝的cookie作为token去做坏事。

跨域的解决方案

1. jsonp

原理:利用script标签实现

需要服务的支持

只能get请求

2. nginx反向代理

思路:利用nginx反向代理把跨域为不跨域,支持各种请求方式

缺点:需要在nginx进行额外配置,语义不清晰

3. CORS

请求分为两类

1.简单请求

需要同时满足以下两个请求:

<1>请求方式

  1. HEAD
  2. GET
  3. POST

<2>Http请求头不超出以下几个字段:

  1. Accept
  2. Accept-Language
  3. Content-Language
  4. Last-Event-ID
  5. Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

当浏览器发现ajax请求属于简单请求,就会在请求头中添加Origin字段,如Origin:http://manage.leyou.com

Origin中会指出当前请求属于哪个域(协议+域名+端口)。服务会根据这个值决定是否允许其跨域。

如果服务器允许跨域,需要再返回的响应头携带以下信息:

Access-Control-Allow-Origin: http://manage.leyou.com

Access-Control-Allow-Credentials: true

在本次遇到的问题,实际上发起了一次简单的请求,在Response Headers中可以看到

2. 特殊请求

不符合简单请求的会被浏览器判断为特殊请求,例如PUT请求。

预检请求

特殊请求会在正式通信之前,增加一次HTTP查询请求,成为“预检”请求

浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和head信息字段。只有得到肯定回复,浏览器才会发出正式的XMLHTTPRequest请求,否则就报错

一个预检请求样板

OPTIONS /resources/post-here/ HTTP/1.1 
Host: bar.other 
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 
Accept-Language: en-us,en;q=0.5 
Accept-Encoding: gzip,deflate 
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 
Connection: keep-alive 
Origin: http://foo.example 
Access-Control-Request-Method: POST 
Access-Control-Request-Headers: X-PINGOTHER, Content-Type

预检请求报文中的 Access-Control-Request-Method 首部字段告知服务器实际请求所使用的 HTTP 方法;Access-Control-Request-Headers 首部字段告知服务器实际请求所携带的自定义首部字段。服务器基于从预检请求获得的信息来判断,是否接受接下来的实际请求。

服务器收到预检请求,如果许可跨域,会发出响应:

分析:

除了简单请求中会返回的以下两个头

Access-Control-Allow-Origin: http://manage.leyou.com

Access-Control-Allow-Credentials: true

还有

Access-Control-Allow-Methods: 允许访问的方式

Access-Control-Allow-Headers: 允许携带的头

Access-Control-Max-Age: 本次许可的有效时长,单位是秒,过期之前的ajax请求就无需再次进行预检了


 

猜你喜欢

转载自blog.csdn.net/Cheng_Kohui/article/details/93353825