面试对线记录10 CORS
这个概念的话在今天我面试的时候接触到了,但是我的话可能是因为我做的项目比较菜,所以这部分并没有接触到过,所以我今天仔细学习和记录在这里。
这个玩意说白了就是跨域资源共享,就是说我们平时在不刷新页面时更新网页,在页面加载后从服务器请求数据以及在页面加载后从服务器接受数据等需求的背后,其实都是AJAX技术在默默支持,他使用XMLHttpRequest对象从web服务器请求数据,but不仅仅局限于XML,也可以是纯文本或者JSON文本,但是哟!!!!只能是同源情况下,这就很尴尬了,所以的话就有了CORS这个技术点,他可以允许浏览器向跨源服务器发出XMLHttpRequest请求。
这个技术需要浏览器和服务器支持,but现在浏览器都支持,除了老版本的ie浏览器,我都不想说微软就是个zz了。。。浏览器的话如果发现AJAX跨源,就会添加一些辅助措施来进行帮助请求,当然这种情况对用户来说是透明不感知的。
在CORS的视角下,它把请求分成两种,简单请求和非简单请求,对这两种请求会采用不同的措施。
比如简单请求就包括:HEAD,GET,POST,这几个请求如果跨域的话,就会在头信息中添加一个Origin字段,这个字段会记录该请求来自哪个源,Origin字段会包含协议,域名以及端口,服务器会根据这个值,来判断是否同意这个值。
在服务器拿到这个请求以后,如果Origin这个源不再服务器许可范围内,他就会返回一个正常的HTTP回应,;浏览器会检测这个回应的头信息的话会不会包含Access-Control-Allow-Origin字段,如果不包含,就会抛出一个错误,这种错误不会被状态码识别。
如果Origin这个指定的域名在许可范围内,服务器返回的响应就会多出几个头信息字段
Access-Control-Allow-Origin: http://api.xxxxx.com //这个字段是必须的
Access-Control-Allow-Credentials: true //可选,这个字段的值是bool类型,表示是否允许发送Cookie
Access-Control-Expose-Headers: FooBar //这个字段置顶想拿到的字段的值
Content-Type: text/html; charset=utf-8
非简单请求中就包括PUT,DELETE以及Content-Type字段类型位application/json的请求,针对这些请求的跨域,浏览器会在正式通信之前增加一次HTTP查询请求,称为是“预检”请求;
浏览器会先查询服务器,当前页面所在的域名是否在服务器的许可名单之中,还有可以使用哪些HTTP动词以及头信息字段,只要得到肯定答复,就会发送正常的XMLHttpRequest请求,否则就会报错。
预检请求的头信息我找了一个例子,大概就是这样子:
OPTIONS /cors HTTP/1.1
Origin: http://api.bob.com
Access-Control-Request-Method: PUT //必须字段 表示是个什么类型的请求
Access-Control-Request-Headers: X-Custom-Header //表示浏览器请求会额外发送的头信息字段
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...
大家可以看到请求方法就是OPTIONS,在这里表示这个请求就是用来询问的,头信息里,关键字段就是Origin,表示请求来自什么源。 服务器收到预检请求后,就会检查Origin和Access-Control-Request-Method以及Access-Control-Request-Headers等字段,确认允许跨源请求,就可以做出回应。
HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain
Access-Control-Allow-Origin字段如果为*表示同意任何跨源请求 如果服务器否定了这个预检请求,会返回一个正常的HTTP回应,但是不包含上面的CORS头信息字段,这个时候浏览器就会认定服务器不同意预检请求,所以会触发错误,控制台就会报错。 预检之后的请求,头信息如下:
PUT /cors HTTP/1.1
Origin: http://api.bob.com
Host: api.alice.com
X-Custom-Header: value
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...