Nginx配置跨域资源共享(CORS)的详细示例,涵盖常见场景及安全实践

以下是一个关于Nginx配置跨域资源共享(CORS)的详细示例,涵盖常见场景及安全实践:

一、基础CORS配置(允许所有源)

server {
  listen 80;
  server_name api.example.com;

  location / {
    # 简单请求头配置
    add_header 'Access-Control-Allow-Origin' '*';
    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
    add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization';
    add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';

    # 处理预检请求(OPTIONS)
    if ($request_method = 'OPTIONS') {
      add_header 'Access-Control-Allow-Origin' '*';
      add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
      add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization';
      add_header 'Access-Control-Max-Age' 1728000;  # 缓存20天
      add_header 'Content-Type' 'text/plain; charset=utf-8';
      add_header 'Content-Length' 0;
      return 204;
    }

    proxy_pass http://backend_service;
  }
}

二、安全CORS配置(限制特定源)

server {
  listen 80;
  server_name api.example.com;

  # 定义允许的源(支持通配符)
  map $http_origin $cors_allowed_origin {
    default '';
    ~^https?://(www\.)?example\.com(:[0-9]+)?$ $http_origin;
    ~^https?://(www\.)?trusted-partner\.com(:[0-9]+)?$ $http_origin;
  }

  location / {
    # 动态设置允许的源
    add_header 'Access-Control-Allow-Origin' $cors_allowed_origin;
    add_header 'Access-Control-Allow-Credentials' 'true';  # 允许携带凭证

    # 严格限制请求方法
    add_header 'Access-Control-Allow-Methods' 'GET, POST';
    
    # 限制请求头(根据实际需求调整)
    add_header 'Access-Control-Allow-Headers' 'Content-Type,Authorization';
    
    # 暴露响应头(给前端读取)
    add_header 'Access-Control-Expose-Headers' 'X-Custom-Header';

    # 预检请求处理
    if ($request_method = 'OPTIONS') {
      add_header 'Access-Control-Allow-Origin' $cors_allowed_origin;
      add_header 'Access-Control-Allow-Methods' 'GET, POST';
      add_header 'Access-Control-Allow-Headers' 'Content-Type,Authorization';
      add_header 'Access-Control-Max-Age' 86400;  # 缓存1天
      return 204;
    }

    proxy_pass http://backend_service;
  }
}

三、高级场景配置

1. 携带Cookie/认证信息
server {
  listen 80;
  server_name api.example.com;

  location / {
    add_header 'Access-Control-Allow-Origin' 'https://client.example.com';
    add_header 'Access-Control-Allow-Credentials' 'true';  # 必须显式设置
    add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE';
    add_header 'Access-Control-Allow-Headers' 'Authorization,Content-Type';

    # 预检请求处理
    if ($request_method = 'OPTIONS') {
      add_header 'Access-Control-Allow-Origin' 'https://client.example.com';
      add_header 'Access-Control-Allow-Credentials' 'true';
      add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE';
      add_header 'Access-Control-Allow-Headers' 'Authorization,Content-Type';
      add_header 'Access-Control-Max-Age' 3600;  # 缓存1小时
      return 204;
    }

    proxy_pass http://backend_service;
  }
}
2. 自定义响应头暴露
server {
  listen 80;
  server_name api.example.com;

  location / {
    add_header 'Access-Control-Allow-Origin' 'https://client.example.com';
    add_header 'Access-Control-Expose-Headers' 'X-RateLimit-Limit,X-RateLimit-Remaining';  # 暴露自定义头
    add_header 'Access-Control-Allow-Methods' 'GET';
    add_header 'Access-Control-Allow-Headers' 'Accept';

    proxy_pass http://backend_service;
  }
}

四、安全加固建议

  1. 最小权限原则

    • 仅允许必要的HTTP方法(GET/POST等)
    • 严格限制允许的请求头(避免使用*通配符)
    • 精确匹配允许的源(避免使用泛域名)
  2. 缓存优化

    • 合理设置Access-Control-Max-Age(建议1天以内)
    • 对静态资源设置长期缓存(需配合版本控制)
  3. 日志监控

    log_format cors_log '{$remote_addr} - $remote_user [$time_local] '
                       '"$request" $status $body_bytes_sent '
                       '"$http_origin" "$http_access_control_request_headers"';
    access_log /var/log/nginx/cors_access.log cors_log;
    

五、配置验证与测试

  1. 快速测试

    # 使用curl测试CORS配置
    curl -I -X OPTIONS https://api.example.com/data \
      -H "Origin: https://client.example.com" \
      -H "Access-Control-Request-Method: GET"
    
  2. 浏览器测试

    // 前端测试代码
    fetch('https://api.example.com/data', {
      method: 'GET',
      credentials: 'include'  // 测试携带凭证
    })
    .then(response => console.log(response.headers.get('X-Custom-Header')))
    
  3. 安全扫描

    # 使用核算工具检查CORS配置
    nmap --script http-cors -p 80 api.example.com
    

六、常见问题排查

  1. 预检请求未缓存

    • 检查Access-Control-Max-Age值是否合理
    • 确认浏览器缓存策略(可通过开发者工具查看)
  2. 凭证未携带

    • 确认Access-Control-Allow-Credentials设置为true
    • 检查前端请求是否包含credentials: 'include'
  3. 源不匹配

    • 使用精确域名匹配(避免使用通配符*
    • 检查请求头中的Origin值是否正确

该配置示例覆盖了CORS的核心场景,可根据实际需求扩展以下方向:

  • 集成JWT验证(通过auth_request模块)
  • 实现动态源白名单(通过Lua脚本)
  • 添加速率限制(通过limit_req模块)
  • 配置HTTPS强制跳转(通过rewrite规则)

建议通过浏览器开发者工具的Network面板验证CORS配置,并结合安全扫描工具定期审计跨域策略。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值