AJAX跨域总结

 

 

简介

  跨域是我在日常面试中经常会问到的问题,这词在前端界出现的频率不低,主要原因还是由于安全限制(同源策略, 即JavaScript或Cookie只能访问同域下的内容),因为我们在日常的项目开发时会不可避免的需要进行跨域操作,所以跨域能力也算是前端工程师的基本功之一。

  和大多数跨域的解决方案一样,JSONP也是我的选择,可是某天PM的需求变了,某功能需要改成支持POST,因为传输的数据量比较大,GET形式搞不定。所以折腾了下闻名已久的CORS(跨域资源共享,Cross-Origin Resource Sharing)

 

CORS能做什么:

     正常使用AJAX会需要正常考虑跨域问题,所以伟大的程序员们又折腾出了一系列跨域问题的解决方案,如JSONP、flash、ifame、xhr2等等。

     本文介绍的CORS就是一套AJAX跨域问题的解决方案。

 CORS的原理:

扫描二维码关注公众号,回复: 272314 查看本文章

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

 

 

 

 

 

两种请求

浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。

只要同时满足以下两大条件,就属于简单请求。

(1) 请求方法是以下三种方法之一:
HEAD
GET
POST
(2)HTTP的头信息不超出以下几种字段:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

不是以上内容的就是 非简单请求

 

 

 

 

 

简单请求

浏览器会自动带一个Origin头

GET /cors HTTP/1.1
Origin: http://localhost:8080
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...

 

如果服务器允许这个响应就返回如下内容:

Access-Control-Allow-Origin: http://localhost:8080
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: myheader
Content-Type: text/html; charset=utf-8

 

 

 

 

 

非简单请求

首先会触发一个OPTIONS的预检查请求


 

发送的请求头如下

OPTIONS /ajax.php  HTTP/1.1
Origin: http://localhost:8080
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
Host: localhost:8080
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...

 

服务端发回的响应:

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://localhost:8080
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

 

 

 

 

 

CROS时的请求头和响应头

请求头

请求头 含义
Origin 本次请求来自哪个源(协议 + 域名 + 端口)。服务器根据这个值,决定是否同意这次请求
Access-Control-Request-Method 该字段是必须的,用来列出浏览器的CORS请求会用到哪些HTTP方法
Access-Control-Request-Headers 该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段

 

响应头

响应头 含义
Access-Control-Allow-Origin 该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求
Access-Control-Allow-Methods 该字段必需,它的值是逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法。注意,返回的是所有支持的方法,而不单是浏览器请求的那个方法。这是为了避免多次"预检"请求
Access-Control-Allow-Headers 如果浏览器请求包括Access-Control-Request-Headers字段,则Access-Control-Allow-Headers字段是必需的。它也是一个逗号分隔的字符串,表明服务器支持的所有头信息字段,不限于浏览器在"预检"中请求的字段
Access-Control-Allow-Credentials 它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器
Access-Control-Max-Age 该字段可选,用来指定本次预检请求的有效期,单位为秒。如果填1728000,即允许缓存该条回应1728000秒(即20天),在此期间,不用发出另一条预检请求
Access-Control-Expose-Headers CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定

 

使用反向代理服务器可以解决跨域问题

比如将前端代码部署到nginx上,这样访问的地址是localhost:8080/test/aa.html

假设之前访问的跨域地址是 http://10.0.0.123:8080/hello/go

然后前端将 http://10.0.0.123:8080/hello/go 改成 http://localhost:8080/hello/go 这样就是同源了,浏览器就会将session,cookie都带上请求也放行了

之后nginx将访问/hello/go的这个url改写成 http://10.0.0.123:8080,然后nginx去请求这个真实的跨域地址获取数据后返回,这样就解决了跨域问题了

 

 

 

参考

跨域资源共享 CORS 详解

Javascript异步编程的4种方法

AJAX POST&跨域 解决方案 - CORS

AJAX(XMLHttpRequest)进行跨域请求方法详解(一)

W3C关于CROS介绍

XSS的原理分析与解剖

跨域资源共享(CORS)安全性浅析

浅谈CSRF攻击方式

XSS跨站脚本攻击过程最简单演示

Web服务器反向代理——跨域的另一种方案 

猜你喜欢

转载自xxniao.iteye.com/blog/2346239