跨域资源共享(CORS)配置深度解析与Nginx最佳实践
跨域资源共享(CORS)是现代Web开发的核心安全机制,本文从协议层面向开发者呈现Nginx服务器端的专业配置方案。我们不仅展示基础配置,更深入探讨预检请求处理、缓存优化、安全加固等进阶主题。
1. 全域访问的动态管控方案
server {
listen 443 ssl;
server_name api.example.com;
# 动态Origin处理(需配合map模块)
map $http_origin $cors_origin {
default "";
"~*" $http_origin;
}
location / {
add_header Access-Control-Allow-Origin $cors_origin always;
add_header Vary Origin always;
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
add_header Access-Control-Allow-Headers "Authorization, Content-Type";
add_header Access-Control-Expose-Headers "X-Custom-Header";
# 处理预检请求缓存
if ($request_method = OPTIONS) {
add_header Access-Control-Max-Age 1728000;
add_header Content-Type 'text/plain; charset=utf-8';
return 204;
}
# 应用逻辑处理
proxy_pass http://backend;
}
}
技术要点解析:
-
动态
Origin
处理配合Vary
头部,避免CDN缓存污染 -
always
参数确保错误响应也携带CORS头 -
预检请求单独处理并设置30天缓存时间(1728000秒)
-
显式声明可暴露的响应头(Expose-Headers)
2. 白名单域名安全控制
# 定义允许的域名集合
map $http_origin $allowed_origin {
default "";
~^https?://(app\.example\.com|partner\.example\.net)$ $http_origin;
~^https?://([a-z0-9-]+\.)?example\.org$ $http_origin;
}
server {
location / {
if ($allowed_origin) {
add_header Access-Control-Allow-Origin $allowed_origin;
add_header Access-Control-Allow-Credentials true;
}
# 预检请求处理
if ($request_method = OPTIONS) {
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS";
add_header Access-Control-Allow-Headers "X-Requested-With, Content-Type";
return 204;
}
}
}
安全增强措施:
-
正则表达式实现动态域名白名单
-
精确控制凭证传递(Allow-Credentials)
-
单独处理OPTIONS方法避免主逻辑污染
-
禁用通配符*与Credentials的混用(协议强制要求)
3. 多环境差异化配置
# 环境变量注入(通过Docker/K8s等编排工具)
env DEPLOY_ENV;
map $DEPLOY_ENV $cors_policy {
"production" "strict";
"staging" "relaxed";
default "open";
}
server {
location / {
# 根据环境切换策略
if ($cors_policy = strict) {
include cors/production.conf;
}
if ($cors_policy = relaxed) {
include cors/staging.conf;
}
if ($cors_policy = open) {
include cors/development.conf;
}
}
}
生产级方案特征:
-
环境隔离配置(开发/测试/生产)
-
模块化配置文件管理
-
部署时策略自动切换
-
审计日志记录跨域请求
4. 安全监控与异常处理
log_format cors_audit '$remote_addr - $http_origin - $http_user_agent '
'$request_method "$request_uri" $status';
server {
location / {
# 异常请求拦截
if ($http_origin !~* (approved_domains)) {
access_log /var/log/nginx/cors_violations.log cors_audit;
return 403 "Invalid origin";
}
# 可疑头信息检测
if ($http_access_control_request_method !~* ^(GET|POST|PUT|DELETE)$) {
add_header X-CORS-Alert "Suspicious Method Request" always;
}
}
}
安全监控策略:
-
专用日志格式记录跨域请求
-
实时检测非常规请求方法
-
可疑来源自动拦截与告警
-
结合SIEM系统进行行为分析
调试验证方法
# 完整预检请求测试
curl -X OPTIONS https://api.example.com/data \
-H "Origin: https://app.example.com" \
-H "Access-Control-Request-Method: POST" \
-H "Access-Control-Request-Headers: X-API-Key" \
-v
# 响应头验证
curl -I https://api.example.com/data \
-H "Origin: https://app.example.com"
验证要点:
-
预检请求返回204状态码
-
正确返回Allowed-Methods和Allowed-Headers
-
生产环境禁用敏感头信息(如Server头)
-
检查Vary头是否正确设置
高级配置建议
- 性能优化:
- 静态资源设置长期缓存策略
location ~* \.(woff2|js|css)$ {
add_header Access-Control-Allow-Origin *;
expires 365d;
}
- 安全加固:
add_header Content-Security-Policy "default-src 'self'";
add_header X-Content-Type-Options nosniff;
- 协议升级:
if ($http_origin ~* "^https://") {
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
}
总结与最佳实践
- 最小权限原则:
-
精确指定Allowed-Origin域名
-
按需开放HTTP方法和请求头
- 防御性编程:
-
校验Origin头格式有效性
-
防范Null Origin攻击
- 监控审计:
-
实时监控CORS违规事件
-
定期审计配置有效性
- 协议遵循:
-
正确处理CORS与Cookie的交互
-
遵循Fetch Metadata规范