Nginx处理CORS(跨站资源共享)
我在部署 NGINX反向代理https 启用了 docs.cloud-atlas.io 构建 "云图 -- 云计算图志: 探索" 自建网站。但是发现一个问题,原本 utterances 构建的 Sphinx文档评论系统 无法展示了。
这个问题是我刚切换到 FreeBSD XFCE桌面 作为工作平台时发现的,使用浏览器 Firefox 存在这个现象,而之前在 macOS 平台使用Safari就没有这个问题。看来Firefox有什么特别之处,所以开启 Firefox 的developer tools 观察页面加载情况,就发现原来 https://uteranc.es/client.js 无法加载,提示 CORS error 。
简单来说,处于网站安全,一个HTTPS加密网站的所有页面应该是(最好)从同一个域名提供,也就是客户端浏览器仅信任自己访问的网站。但是,如果页面中嵌入了其他网站资源,那么从安全严格来讲,客户端有一定理由怀疑存在安全隐患。所以,如果浏览器设置较高安全等级,是会拒绝这种跨域内容的。
解决的方法也比较简单,就是在NGINX发送给客户端ORIGN请求的响应内容的头部插入 Access-Control-Allow-Origin
字段,表示网站信任和接受那哪些网站提供的资源。o
对于我这里的实践 NGINX反向代理https ,实际上只要在后端NGINX(也就是反响代理所指向的真正提供内容的后端NGINX服务器上)配置:
CORS
server {
include /etc/nginx/includes/server.conf;
server_name cloud-atlas.io www.cloud-atlas.io;
root /var/web/cloud-atlas.io/www;
}
server {
include /etc/nginx/includes/server.conf;
server_name docs.cloud-atlas.io;
root /var/web/cloud-atlas.io/docs;
location /discovery {
add_header 'Access-Control-Allow-Origin' 'https://utteranc.es';
alias /var/web/cloud-atlas.io/docs.discovery;
}
}
不过,还是存在一点问题,如果访问用户登陆过github,那么 utteranc.es
还会调用 api.github.com
,所以实际上我们需要设置多个domain的CORS。为了能够方便配置,采用 Nginx配置文件的include 包含一个domain的map来解决:结合两个配置文件
/etc/nginx/conf.d/cloud-atlas.io.conf
:
include /etc/nginx/includes/origin_map.conf;
server {
include /etc/nginx/includes/server.conf;
server_name cloud-atlas.io www.cloud-atlas.io;
root /var/web/cloud-atlas.io/www;
}
server {
include /etc/nginx/includes/server.conf;
server_name docs.cloud-atlas.io;
root /var/web/cloud-atlas.io/docs;
location /discovery {
add_header 'Access-Control-Allow-Origin' '$cors' always;
alias /var/web/cloud-atlas.io/docs.discovery;
}
}
/etc/nginx/includes/origin_map.conf
:
origin_map.conf
配置了一个NGINX map#Map the needed frontend URLS to the cors variable
map "$http_origin" $cors {
default '';
"~^https?://api.github.com?$" "$http_origin";
"~^https?://utteranc.es?$" "$http_origin";
}
全面放开nginx的CORS配置
使用以下nginx配置可以放开CORS:
#
# Wide-open CORS config for nginx
#
location / {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
#
# Om nom nom cookies
#
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
#
# Custom headers and headers various browsers *should* be OK with but aren't
#
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
#
# Tell client that this pre-flight info is valid for 20 days
#
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
if ($request_method = 'POST') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
}
}
参考
Navigating CORS: Enabling Multi-Origin Integration with NGINX 快速构建map,配置多域名CORS
How to allow access via CORS to multiple domains within nginx 可以使用map或者通过if判断
Kubernetes Ingress-nginx CORS: How to allow multiple Origins? 在k8s上部署nginx ingress时配置多域名CORS