使用Nginx作为Web服务器或反向代理是目前主流方案之一。Nginx不仅支持高并发、高性能处理,还在HTTPS支持、跨域头设置方面表现稳定,具备极高的可配置性。如何在Nginx中配置SSL证书并确保跨域请求被正确允许,便成为技术实践中的重要一环。
一、理解CORS与SSL的关系
1. 什么是CORS?
跨域资源共享(CORS)是现代浏览器出于安全考虑,在执行JavaScript脚本时的一种同源策略限制。当一个域名上的网页脚本试图请求另一个域名(如不同的协议、端口、域名)的资源时,如果服务器未明确在响应中声明允许该跨域请求,浏览器会直接拦截。
2. 为什么HTTPS下跨域配置更为严格?
开启SSL(即使用HTTPS)后,浏览器对跨域请求的校验会更加严格,尤其涉及到Cookie、Authorization等敏感头部信息时,仅支持带有明确Access-Control-Allow-Origin等字段的响应。
CORS配置和SSL配置虽然是两个模块,但必须协同工作,才能让HTTPS跨域请求被浏览器接受。
二、Nginx配置SSL证书基础流程
1. 申请或准备SSL证书
SSL证书可以选择自签名证书(适用于测试环境),免费证书(适用于中小网站),商用CA机构签发证书(适合企业生产环境)。
常见SSL文件结构如下:
- certificate.crt:证书文件
- private.key:私钥文件
- ca_bundle.crt:中间证书(某些CA会单独提供)
2. 基础Nginx SSL配置示例
server {
listen 443 ssl;
server_name api.example.com;
ssl_certificate /etc/nginx/ssl/certificate.crt;
ssl_certificate_key /etc/nginx/ssl/private.key;
ssl_trusted_certificate /etc/nginx/ssl/ca_bundle.crt;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
proxy_pass http://127.0.0.1:8000;
}
}
通过此配置,https://api.example.com 端口将启用SSL安全通信。下一步将配置跨域响应头。
三、Nginx中添加CORS跨域响应头的方式
在Nginx中添加跨域响应头非常直接,可通过add_header命令实现。
1. 基本跨域支持配置(静态开放)
location / {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization';
if ($request_method = 'OPTIONS') {
return 204;
}
proxy_pass http://127.0.0.1:8000;
}
该配置中:
*
代表允许任意源访问,适用于无敏感信息的开放型API;OPTIONS
请求返回204避免浏览器挂起;- 支持常见的跨域请求方法与请求头。
2. 动态跨域配置(指定来源)
如果需要根据来源进行跨域判断(如只允许 https://www.example.com 请求),可使用 $http_origin 变量动态设置:
location / {
if ($http_origin ~* "^https://www\.example\.com$") {
add_header 'Access-Control-Allow-Origin' "$http_origin";
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization';
}
if ($request_method = 'OPTIONS') {
return 204;
}
proxy_pass http://127.0.0.1:8000;
}
此方案配合 credentials:true
使用场景(如Cookie认证)尤其重要。
四、完整示例:HTTPS + CORS 支持 API 接口
server {
listen 443 ssl;
server_name api.example.com;
ssl_certificate /etc/nginx/ssl/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location /api/ {
if ($http_origin ~* "^https://(www\.)?example\.com$") {
add_header 'Access-Control-Allow-Origin' "$http_origin" always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always;
}
if ($request_method = 'OPTIONS') {
return 204;
}
proxy_pass http://backend.internal:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
重点在于:
- 使用
always
确保即使发生错误响应也返回CORS头; proxy_set_header
传递真实客户端IP等信息;- 明确区分生产环境来源域名,避免开放所有源。
五、常见错误与排查建议
1. 浏览器提示 CORS policy: No 'Access-Control-Allow-Origin' header
说明后端响应未包含必要跨域响应头,检查是否HTTPS接口返回了错误状态(如403、500),导致add_header
失效?是否使用了 return
或 error_page
,未携带CORS头?Nginx版本是否支持 add_header ... always
?
2. 带凭证请求但未设置 Allow-Credentials
解决方法:
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Origin' "$http_origin";
注意此时 Access-Control-Allow-Origin
不能使用 *,必须是具体域名。
3. HTTPS请求失败或浏览器报“证书不安全”
- 证书未被信任:检查是否为自签名证书;
- 漏配中间证书:使用
.crt
和ca_bundle
拼接后的 fullchain; - 客户端未开启TLS1.2/1.3兼容。
六、安全性注意事项
虽然跨域支持有助于前后端分离和资源共享,但错误配置可能导致跨站数据泄漏、身份伪造等安全隐患:
1. 严禁生产环境使用Access-Control-Allow-Origin: *
配合Allow-Credentials: true
;
2. 不要将CORS设置在全局 http
段,容易造成误开放;
3. 避免将整个网站路径设为跨域,建议仅在 /api/
等接口路径上配置;
4. 使用 Referer
或 Origin
白名单校验结合 token 鉴权机制,更安全。
随着前后端分离架构的普及和HTTPS通信的常态化,跨域请求在带SSL的环境下已成为常规需求。通过合理配置Nginx的SSL证书及跨域响应头,不仅可以提升系统安全性,还能保证API接口的灵活可控访问。
开发者和运维人员在实际部署过程中,应结合业务场景、数据敏感性和浏览器兼容性等因素,采取差异化配置策略,做到既满足前端调用,又控制跨域权限,从而打造安全、高效、规范的Web服务平台。