1. 为什么需要Nginx跨域配置前端开发者在对接API接口时经常会遇到浏览器的CORS跨域资源共享限制。当你的前端页面运行在https://example.com而API服务部署在https://api.example.com时浏览器会阻止这种跨域请求。这就是为什么我们需要在Nginx中配置跨域头信息。跨域问题本质上是一个浏览器安全策略与HTTP协议本身无关。服务器之间直接通信时不存在跨域限制但浏览器会主动拦截不符合CORS规范的跨域请求。通过Nginx配置我们可以告诉浏览器哪些跨域请求是被允许的。2. 核心配置参数解析2.1 基础跨域配置在Nginx配置文件中最基础的跨域配置如下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; add_header Access-Control-Expose-Headers Content-Length,Content-Range; }这个配置中Access-Control-Allow-Origin: 指定允许访问资源的源*表示允许所有域名Access-Control-Allow-Methods: 允许的HTTP方法Access-Control-Allow-Headers: 允许的请求头Access-Control-Expose-Headers: 允许客户端访问的响应头2.2 带凭证的跨域请求当请求需要携带cookie等凭证信息时配置会更复杂location / { add_header Access-Control-Allow-Origin https://example.com; add_header Access-Control-Allow-Credentials true; 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; if ($request_method OPTIONS) { add_header Access-Control-Max-Age 1728000; add_header Content-Type text/plain; charsetutf-8; add_header Content-Length 0; return 204; } }关键区别在于不能使用通配符*必须指定具体域名需要添加Access-Control-Allow-Credentials: true需要特别处理OPTIONS预检请求3. 实际应用场景配置3.1 前后端分离项目配置假设前端部署在https://web.example.com后端API在https://api.example.comserver { listen 443 ssl; server_name api.example.com; ssl_certificate /path/to/cert.pem; ssl_certificate_key /path/to/key.pem; location / { add_header Access-Control-Allow-Origin https://web.example.com; add_header Access-Control-Allow-Methods GET, POST, PUT, DELETE, OPTIONS; add_header Access-Control-Allow-Headers Authorization,Content-Type; add_header Access-Control-Allow-Credentials true; if ($request_method OPTIONS) { return 204; } proxy_pass http://backend_server; } }3.2 多域名白名单配置如果需要支持多个域名的跨域访问可以使用变量和mapmap $http_origin $cors_origin { default ; ~^https://(web1|web2)\.example\.com$ $http_origin; } server { ... location / { if ($cors_origin) { add_header Access-Control-Allow-Origin $cors_origin; add_header Access-Control-Allow-Credentials true; add_header Vary Origin; } ... } }4. 常见问题与解决方案4.1 配置不生效的可能原因缓存问题浏览器可能缓存了之前的响应头。解决方案强制刷新缓存CtrlF5在开发工具中禁用缓存添加Cache-Control: no-cache头配置位置错误跨域头必须添加到正确的location块中。确保配置在匹配的location块内没有被其他配置覆盖SSL证书问题如果使用HTTPS确保证书有效证书包含所有使用的域名或使用通配符证书4.2 预检请求(OPTIONS)处理浏览器在发送某些跨域请求前会先发送OPTIONS请求。常见问题OPTIONS请求返回405location / { if ($request_method OPTIONS) { add_header Access-Control-Allow-Origin $http_origin; add_header Access-Control-Allow-Methods GET, POST, OPTIONS; add_header Access-Control-Allow-Headers Content-Type,Authorization; add_header Access-Control-Max-Age 1728000; add_header Content-Type text/plain; charsetutf-8; add_header Content-Length 0; return 204; } }预检请求缓存通过Access-Control-Max-Age控制缓存时间5. 高级配置技巧5.1 动态允许源如果需要根据请求动态设置允许的源set $cors ; if ($http_origin ~* https://(.*\.)?example\.com) { set $cors $http_origin; } location / { if ($cors ! ) { add_header Access-Control-Allow-Origin $cors; add_header Access-Control-Allow-Credentials true; add_header Vary Origin; } }5.2 结合反向代理当Nginx作为反向代理时确保后端返回的CORS头不会被覆盖location /api/ { proxy_pass http://backend; # 移除后端可能设置的CORS头 proxy_hide_header Access-Control-Allow-Origin; proxy_hide_header Access-Control-Allow-Credentials; # 设置自己的CORS头 add_header Access-Control-Allow-Origin $http_origin; add_header Access-Control-Allow-Credentials true; }5.3 性能优化建议合理设置Access-Control-Max-Age对于稳定的API可以设置较长的缓存时间如1728000秒/20天减少不必要的头信息只添加必要的Allow-Headers使用Vary头当根据Origin动态设置时添加Vary: Origin防止缓存问题6. 安全注意事项不要随意使用通配符*在生产环境中尽量避免使用Access-Control-Allow-Origin: *特别是当请求需要携带凭证时。严格限制允许的方法只开放必要的HTTP方法例如add_header Access-Control-Allow-Methods GET, POST;验证来源域名使用正则表达式严格验证允许的来源if ($http_origin ~* ^https://(www\.)?example\.com$) { add_header Access-Control-Allow-Origin $http_origin; }敏感接口保护对于敏感接口建议不使用CORS改为同域访问或通过其他认证方式加强保护7. 测试与验证配置完成后可以通过以下方式验证curl测试curl -I -X OPTIONS https://api.example.com/resource \ -H Origin: https://web.example.com \ -H Access-Control-Request-Method: POST浏览器开发者工具查看Network标签中的请求和响应头确保没有CORS错误在线验证工具使用Postman或类似的API测试工具专门针对CORS的在线验证服务8. 实际案例电商网站配置假设一个电商网站主站https://shop.example.comAPIhttps://api.shop.example.com管理后台https://admin.shop.example.comNginx配置示例map $http_origin $cors_origin { default ; ~^https://(shop|admin)\.example\.com$ $http_origin; } server { listen 443 ssl; server_name api.shop.example.com; ssl_certificate /path/to/cert.pem; ssl_certificate_key /path/to/key.pem; location / { if ($cors_origin) { add_header Access-Control-Allow-Origin $cors_origin; add_header Access-Control-Allow-Credentials true; add_header Vary Origin; } add_header Access-Control-Allow-Methods GET, POST, PUT, DELETE, OPTIONS; add_header Access-Control-Allow-Headers Content-Type,Authorization,X-Requested-With; add_header Access-Control-Expose-Headers X-Total-Count; if ($request_method OPTIONS) { add_header Access-Control-Max-Age 86400; add_header Content-Type text/plain; charsetutf-8; add_header Content-Length 0; return 204; } proxy_pass http://backend; } }9. 与其他技术的结合9.1 与WebSocket配合WebSocket不受同源策略限制但有时也需要CORS头location /ws/ { proxy_pass http://websocket_backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; # 仍然建议添加CORS头 add_header Access-Control-Allow-Origin https://example.com; add_header Access-Control-Allow-Credentials true; }9.2 与GraphQL API配合GraphQL通常使用POST请求需要特别注意location /graphql { add_header Access-Control-Allow-Origin https://example.com; add_header Access-Control-Allow-Methods POST, OPTIONS; add_header Access-Control-Allow-Headers Content-Type,Authorization; if ($request_method OPTIONS) { return 204; } proxy_pass http://graphql_backend; }10. 调试技巧与工具Nginx调试模式nginx -t # 测试配置 tail -f /var/log/nginx/error.log # 查看错误日志浏览器开发者工具查看Console和Network标签注意CORS相关错误信息专用测试页面!DOCTYPE html html body script fetch(https://api.example.com/data, { credentials: include }) .then(response response.json()) .then(data console.log(data)) .catch(error console.error(Error:, error)); /script /body /html跨域问题诊断流程检查请求是否真的跨域检查响应头是否正确检查是否有OPTIONS预检请求检查证书和协议是否匹配检查是否有缓存问题