nginx 处理跨域 (cors)

阅读 207
收藏 1
2018-12-28
原文链接:original.unordered.org

HTML5 的到来促进了前后端分离开发的发展,所谓分离即分离接口和页面。 部署的时候一般都把接口部署在单独的域名下面,带上 api 前缀,页面则用主域名。 例如:

页面域名:www.example.com

接口域名则为:api.example.com

同源策略

同源策略 限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。

上面的两个域名不相同,所以会被浏览器所限制,页面中 ajax 调用 api.example.com 接口 将不会成功。一般错误如下:

Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin XXX is therefore not allowed access. The response had HTTP status 4XX.

使用 nginx 解决跨域

一开始网上找了很多教程,都说的不清楚,写的也不完整,索性研究了一下文档,帮大家趟个坑。

if ($request_method = 'OPTIONS') {
  return 204;
}
add_header Access-Control-Allow-Origin * always;
add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS, PUT, PATCH, DELETE, HEAD" always;
add_header Access-Control-Max-Age 86400 always;

解析

这里判断请求方法是否为 OPTIONSOPTIONS 请求方法为预检请求,当浏览器发现需要跨域请求 的时候会先使用该方法请求服务器,服务器需要返回正确的信息后浏览器才会接着发送正式请求(一般除了 GET 方法外的跨域请求都会先发送预检请求),预检请求的返回状态码为 204 代表成功,其它均为失败。 预检请求没有返回的 Body

if ($request_method = 'OPTIONS') {
  return 204;
}

这里在返回头中添加 Access-Control-Allow-Origin*,代表允许所有域名下的页面来请求这个 地址(不推荐这样做,一般直接指定为域名,比如 www.example.com)。

add_header Access-Control-Allow-Origin * always;

这里在返回头中添加 Access-Control-Allow-Headers,代表允许在请求该地址的时候带上指定的 请求头,例如:Content-TypeAuthorization,使用逗号(,)拼接起来放在双引号(")中。 需要在请求头中带上其他自定义头的自行添加。

add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;

这里在返回头中添加 Access-Control-Allow-Methods,代表允许使用指定的方法请求该地址。

add_header Access-Control-Allow-Methods "GET, POST, OPTIONS, PUT, PATCH, DELETE, HEAD" always;

这里添加了 Access-Control-Max-Age,它代表着在 86400 秒之内不用请求该地址的时候 不需要再进行预检请求,也就是跨域缓存。根据需要设置时长就行。

add_header Access-Control-Max-Age 86400 always;

注意:上面的 add_header 最后都加上了 always,它表示不管返回状态码是多少都 会使 add_header 生效,有些时候服务端可能会返回 4XX 的状态码,这时候如果少了 always 会导致 add_header 失效,从而导致浏览器报跨域错误。 参考nginx文档

作者: unordered
链接: original.unordered.org/timelines/5…
原创文章,著作权归作者所有。商业转载请联系 unordered 获得授权,非商业转载请注明原链接及出处。

评论