用户工具

站点工具


跨域资源共享 CORS

跨域是浏览器限制,但是如果服务器设置了 CORS 相关配置,在返回服务器的信息头部会加上 Access-Control-Allow-Origin,浏览器看到这个字段的值与当前的源匹配,就会解锁跨域限制。

HTTP/1.1 200 OK
Date: Sun, 24 Apr 2016 12:43:39 GMT
Server: Apache
Access-Control-Allow-Origin: http://www.acceptmeplease.com
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: application/xml
Content-Length: 423

对于 CORS,请求分两种。

简单请求

  • 请求方法使用 GET、POST 或 HEAD
  • Content-Type 设为 application/x-www-form-urlencoded、multipart/form-data 或 text/plain

符合上面两个条件的都为 CORS 简单请求。简单请求都会直接发到服务器,会造成 CSRF。

预检请求

不符合简单请求要求的请求都需要先发送预检请求(Preflight Request)。浏览器会在真正请求前发送 OPTION 方法的请求向服务器询问当前源是否符合 CORS 目标,验证通过后才会发送正式请求。

例如使用 application/json 传参的 POST 请求就是非简单请求,会在预检中被拦截。

再例如使用 PUT 方法请求,也会发送预检请求。

上面提到的可以防范 CSRF 的例外,就是指预检请求。即使跨域成功请求预检,但真正请求并不能发出去,这就保证了 CSRF 无法成功。

与同域不同,用于跨域的 CORS 请求默认不发送 Cookie 和 HTTP 认证信息,前后端都要在配置中设定请求时带上 cookie。

这就是为什么在进行 CORS 请求时 axios 需要设置 withCredentials: true

下面是 node.js 的后台 koa 框架的 CORS 设置:

/**
 * CORS middleware
 *
 * @param {Object} [options]
 *  - {String|Function(ctx)} origin `Access-Control-Allow-Origin`, default is request Origin header
 *  - {String|Array} allowMethods `Access-Control-Allow-Methods`, default is 'GET,HEAD,PUT,POST,DELETE,PATCH'
 *  - {String|Array} exposeHeaders `Access-Control-Expose-Headers`
 *  - {String|Array} allowHeaders `Access-Control-Allow-Headers`
 *  - {String|Number} maxAge `Access-Control-Max-Age` in seconds
 *  - {Boolean} credentials `Access-Control-Allow-Credentials`
 *  - {Boolean} keepHeadersOnError Add set headers to `err.header` if an error is thrown
 * @return {Function} cors middleware
 * @api public
 */

顺带一提,Access-Control-Allow-Credentials设为true时,Access-Control-Allow-Origin 强制不能设为 *,为了安全,也是挺麻烦啊...


来源:usubenifantasy 前端网络安全必修 1

/opt/bitnami/dokuwiki/data/pages/技术/cors.txt · 最后更改: 2019/12/25 07:39 由 superuser