Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

跨域CORS小记 #27

Open
fwon opened this issue Jan 23, 2017 · 0 comments
Open

跨域CORS小记 #27

fwon opened this issue Jan 23, 2017 · 0 comments

Comments

@fwon
Copy link
Owner

fwon commented Jan 23, 2017

浏览器对XMLHttpRepeat或Fetch发起的请求都有同域的限制。

在调用跨域API的时候,用的最多的是jsonp的方式。

jsonp
jsonp的原理就是往页面添加一个<script>标签,通过在src连接后面添加callback=callbackName参数,并在页面定义callbackName方法。后端获取参数名后往页面输出callbackName(data); 即执行了页面定义好的回调函数,将数据返回给前端页面。
本质上这也是一种跨域请求,但是浏览器对这种直接引入链接的方式并没有限制。就像直接在页面上用<script>引入第三方js,css文件。

这种方式的缺点是,如果原先接口不是采用jsonp的方式,改动影响面较大。

CORS
CORS也可以解决跨域请求的问题,然而思路就不一样了。

CORS也需要后端配合,浏览器发起ajax请求时,会在HTTP请求头中携带Origin头,表示当前发起请求的域名。通过对比Origin和Request URL,即请求接口域名,浏览器自动判断该请求是否为跨域请求。

跨域ajax请求可以分为两种情况:简单请求和复杂请求。
简单请求包括:GET,HEAD请求,和Content-Type为application/x-www-form-urlencoded, multipart/form-data 或 text/plain 的POST请求。
复杂请求为:除了GET,HEAD,POST之外的其他请求,也包括Content-type为application-xml或者 text/xml的POST请求

当浏览器发起的请求为简单ajax请求时。服务端接收到请求后,会返回数据给浏览器。这时候浏览器会检查接口的返回头,判断是否有Access-Control-Allow-xxx相关的头部。如果Access-Control-Allow-Origin为*,或者白名单有发起请求的Origin。那么浏览器就会将数据返回给前端,否则的话请求将不会返回,浏览器直接在控制台报出跨域异常信息。

当浏览器发起的请求为复杂ajax请求时,浏览器首先会往后端发起一个OPTIONS请求,并提交字段Access-Control-Request-Method,询问服务器是否支持这种Type请求方式,比如Access-Control-Request-Method: POST。

服务端接收到请求后,会返回数据给浏览器。这时候浏览器会检测接口的返回头,判断Access-Control-Allow-Origin是否设置允许跨域,同时检查Access-Control-Request-Method是否包括请求的方式。通常还会返回Access-Control-Max-Age用于告知浏览器多长时间内对同样的请求免除发起OPTIONS预请求。剩下的处理方式跟简单请求一致。

CORS携带cookie
有些接口需要判断用户状态,在发起请求的时候要携带cookie。我们知道同域的请求都会自动带上cookie。对于跨域的ajax, XMLHttpRequest 方法中有个参数withCredentials, 通过设置参数为xhr.withCredentials = true,接口请求中也会自动带上cookie。当然这里面后端也要做点工作。

通过Set-Cookie头部,服务器能为浏览器设置cookie,可以同时支持发送多个Set-Cookie头设置多个cookie,并且通过path字段设置cookie的有效存放路径,浏览器发起的请求只有命中了path, 才能携带该cookie到服务器。 还有必须设置另外一个头部Access-Control-Allow-Credentials,当该值为true的时候,才允许往接口所在域名下发cookie。当ajax请求中的withCredentials为true时,浏览器会将cookie保存到域名下。而当前端请求中并没有设置withCredentials:true,即使后端返回了Access-Control-Allow-Credentials:true,浏览器也不会保存cookie。

所以在跨域请求的时候,往往要在第一次请求的时候保存cookie,后面请求的时候才能将此cookie携带给后端。

为了安全考虑,后端在设置Access-Control-Allow-Credentials:true的时候,不允许将Access-Control-Allow-Origin设置为*,只能够用添加白名单的方式

调试跨域问题的时候通常还要检查一下前端的提交方式正不正确,后端在获取值的时候怎么获取的。在没有明确的接口文档的时候,双方要确认好数据的提交方式,哪些数据是在Request Url里的,哪些数据是在data里的。才能避免跨域问题带来的调试陷阱。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant