原文地址html
当下不管大厂小厂的先后端开发模式都是先后端分离。之前遇到经过jsonp解决跨域的方式也渐渐的淡出的工程中(不了解jsonp的能够看JSONP跨域请求+简答实现百度搜索)。当前端请求一个接口的时候就会引发跨域,可是当下的前端构建工具都有相应的解决方案,好比webpack中web-dev-server这个插件,就能很简单的启一个本地的服务,而后发请求的时候经过启的本地服务去发送请求,这样就解决跨域问题的一部分了。这种状况下客户端代码和正常非跨域请求一摸同样,不用作任何改变。前端
上面说的方法只是解决了一部分,还有一部分我想你们可能或多或少的会遇到过,就是在登陆场景的时候。服务端的response里面有set-cookie这个字段,在客户端中设置cookie,cookie里面可能包含着的seesionID表示的当前登陆的用户/当前的登陆状态(对这方面不理解的能够看经过cookie和session让http协议变得有状态)。当用户已经登陆而且访问其余页面的时候,服务端会经过cookie中的信息去校验用户登陆状态,若是请求中没有携带身份信息或者身份信息过时(服务端返回401/403)就会跳转到登陆界面。这种状况若是在先后端联调的时候比较麻烦,由于上面方法解决的跨域是不会携带cookie的。目前有两种方法去解决这个:vue
综上: CORS的主要任务都落在服务端,可是若是为了联调服务端的开发代码和生产代码有区别,他们确定是会不搞的。webpack
今天组里的实习生在使用Axios去验证登陆的时候遇到了跨域的问题(前端是vue, 后端是Spring boot)。 通常的请求经过前端设置代理,服务端设置Access-Control-Allow-origin:\*
就能够了,可是登陆时候响应头里面要去set cookie就遇到了问题,结果因为对CORS跨域理解的不是很深入,对预检请求不是很了解,就在axios的issues里面去搜,经过Axios doesn't send cookies with POST and data定位到了问题,原来他后端写的拦截器里面自动把OPTIONS这个请求给过滤掉了,没有让走到后面的流程。ios
CORS的出现是为了解决因为浏览器的同源策略带来的请求跨域问题。git
“跨资源共享(Cross-Origin Resource Sharing(CORS))是经过HTTP Response header来告诉浏览器,让运行在一个origin(domain)上的web应用被容许访问来自不一样源服务器上指定的资源的一种机制。”github
简单来讲: CORS就是经过设置请求的响应头(能经过开发人员控制的基本都是服务端的响应头,客户端的也会有对应的请求头,但通常不会是开发人员去控制的,后面会仔细说)去控制是否容许某个origin的某个/些请求跨域。web
CORS标准新增了一组HTTP首部字段,容许服务端声明哪些源站经过浏览器有权访问哪些资源。对于能对服务器产生反作用的HTTP非简单请求(non-simple request)(特别是除了GET请求之外的请求),浏览器必须首先发送一个方法为OPTIONS的一个预检请求(preflight request)来获取服务器是否容许该请求跨域。服务器获得确认以后,才发起真正的HTTP请求。在预检请求中,服务端也能够通知客户端是否要携带Credentials
.json
某些请求是不会触发预检查请求的,这些请求被成为简单请求(simple request)。 若是一个请求知足下列的全部条件就能够被称为简单请求:axios
application/x-www-form-urlencoded
multipart/form-data
text/plain
不知足上面定义的简单请求,都会发送预检请求。
好比浏览器要发送一个POST请求,content-Type为application/json,新增一个request header为X-TEST
预检请求的步骤:
对于跨域(发生CORS)的请求默认是不会带上凭证信息(credentials)的,若是要发送凭证信息(credentials)就须要设置对应的标识位。
请求:
响应:
HTTP规范规定Access-Control-Allow-Origin
不能是通配符*而且只能是单一的origin
。这是由于若是能设置多个的话,证实该服务器就能接受多个域名下面的cookie,这是很危险的。
Access-Control-Allow-Origin: <origin> | *
origin参数的值制定了容许访问服务器资源的外域URI。对于不须要携带身份凭证的请求,服务器能够指定这个字段的值为通配符*,表示容许来自全部域的请求。
该头信息服务器把容许浏览器访问的头放入白名单,例如:
Access-Control-Expose-Headers: X-My-Custom-Header, X-Another-Custom-Header
在跨域访问的时候,XHR对象的getResponseHeader()只能拿到一些最基本的响应头。
指定了预检请求(preflight)请求的结果能被缓存多久(秒为单位)。
当浏览器的credentials设置为true时,是否容许浏览器读取response的内容
做为预检请求的响应头,指明了实际请求所容许的HTTP方法。
用于预检请求的响应。其指明了实际请求中容许携带的首部字段。 以逗号分割。
这些字段通常无需手动设置。
预检请求或实际请求的源站。
不包含任何路径,只是服务器的名称。(不论是否为跨域,这个字段都被发送。)
用于预检请求。其做用是,将实际请求所使用的 HTTP 方法告诉服务器。