一、为什么需要跨域方案
1995年Netscape公司在浏览器中引入中了同源策略,最初其含义是A网页设置的cookie,B网页不能打开,为了保证用户的信息安全,防止被恶意的网站窃取用户的数据。
这个是浏览器中十分重要的策略,后来基本上所有的浏览器都实现了同源策略。虽然保证了浏览器的安全,但是在实际使用中也限制了一些需要进行跨域的使用场景,例如单点登录,这时候就需要有完善的跨域方案。
二、什么是CORS
CORS是Cross-origin resource sharing,跨域资源共享,是一个W3C的标准,一个常用的跨域共享方案。
目前Ajax请求只允许同源访问,不允许跨域访问,而CORS方案允许浏览器向跨源服务器发出XMLHttpRequest请求,CORS需要浏览器和服务器同时配合进行支持。
简单的理解,CORS方案完全由浏览器进行操作,用户无感,在发起请求的时候判断是跨域的请求会自动添加一些附加头信息,而后端的服务器识别并添加对这类请求的支持,CORS针对不同的请求类型有不同的请求方式,一是simple request,二是not-so-simple request。
符合以下两种情况的请求是simple request
1、请求的方法是以下三种方法之一。
- HEAD
- GET
- POST
2、HTTP header不超出以下几个字段
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
超出这两种情况的都属于not-so-simple-request。
三、simple request
针对simple request,在发起请求以后,浏览器判断是跨域的请求以后会自动在请求header中添加Origin字段, 本次请求来自哪个源,注意是否同源是根据“协议+域名+端口”三者来判断的。
服务端接受到请求以后需要查看Origin字段的值判断属于哪个源,是否允许对于这个源的访问请求。如果允许请求的话,那么响应中的header会出现以下这几个字段:
Access-Control-Allow-Origin Access-Control-Allow-Credentials Access-Control-Allow-Credentials Content-Type
其中
Access-Control-Allow-Origin、Content-Type是必须的字段,Access-Control-Allow-Origin字段说明允许来自某个源的跨域请求,它的值要么是请求时Origin字段的值,要么是一个*(设置为*的情况下,无法跨域获取cookie),表示接受任意域名的请求。
Access-Control-Allow-Credentials字段可选,代表是否允许浏览器发送cookie,默认情况下不允许,若需要允许则设置为true,特别说明,浏览器客户端发起XMLHttpRequest的时候需要同步设置withCredentials属性为true。
Access-Control-Expose-Headers属于可选字段,CORS请求XMLHttpRequest对象的getResponseHeader方法只能获取到Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma这几个字段,其他的header字段无法获取,若要获取其他字段,则将字段名设置在Access-Control-Expose-Headers字段中。
四、not-so-simple-request
针对not-so-simple-request,例如DELETE请求,浏览器如果发现这种请求,那么会先发起一个OPTIONS请求,表示这个请求是用来进行询问的,其中header中会有以下字段:
- Origin
表示请求来自哪个源。 - Access-Control-Request-Method
希望查询是否支持的HTTP方法,一般也就是客户端会发起的方法,例如上面提到的DELETE。 - Access-Control-Request-Headers
CORS请求额外发送的header字段
当服务端收到这个OPTIONS请求以后,如果不支持跨域请求,则不添加任何header信息,直接返回即可,如果支持这个跨域请求,则添加相应的header
Access-Control-Allow-Methods Access-Control-Allow-Headers Access-Control-Allow-Credentials Access-Control-Max-Age
- Access-Control-Allow-Methods
服务器支持的所有跨域请求的方法,用逗号分隔。 - Access-Control-Allow-Headers
跨域请求所有支持的请求头字段信息,用逗号分隔。 - Access-Control-Allow-Credentials
同simple request中的定义。 - Access-Control-Max-Age
可选,表示本次OPTIONS请求可以被浏览器缓存的时间。