Nginx配置SSL后仍遇No 'Access-Control-Allow-Origin' header错误求助
我用Nginx搭建了代理服务器,通过Certbot安装了SSL证书。完成配置后前端出现No 'Access-Control-Allow-Origin' header错误,已经在.conf文件中添加add_header 'Access-Control-Allow-Origin' '*'指令,但问题依旧存在。
错误信息:
Access to fetch at 'https://api.mywebsite.com/api/users' from origin 'https://panel.mywebsite.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
前端站点: https://panel.mywebsite.com
后端站点: https://api.mywebsite.com
后端API配置文件(/etc/nginx/sites-enabled/api.mywebsite.com)
server { server_name api.mywebsite.com; add_header Access-Control-Allow-Origin https://panel.mywebsite.com; location / { proxy_pass http://localhost:1337; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_redirect off; } listen [::]:443 ssl; # managed by Certbot listen 443 ssl; # managed by Certbot ssl_certificate /etc/letsencrypt/live/api.mywebsite.com/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/api.mywebsite.com/privkey.pem; # managed by Certbot include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot } server { if ($host = api.mywebsite.com) { return 301 https://$host$request_uri; } # managed by Certbot listen 80; listen [::]:80; server_name api.mywebsite.com; return 404; # managed by Certbot }
前端站点配置文件(/etc/nginx/sites-enabled/panel.mywebsite.com)
server { server_name panel.mywebsite.com; location / { proxy_pass http://127.0.0.1:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_redirect off; } listen [::]:443 ssl; # managed by Certbot listen 443 ssl; # managed by Certbot ssl_certificate /etc/letsencrypt/live/panel.mywebsite.com/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/panel.mywebsite.com/privkey.pem; # managed by Certbot include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot } server { if ($host = panel.mywebsite.com) { return 301 https://$host$request_uri; } # managed by Certbot listen 80; listen [::]:80; server_name panel.mywebsite.com; return 404; # managed by Certbot }
问题出在Nginx的add_header指令作用范围和跨域预检请求的处理上,按以下步骤修改即可解决:
调整CORS头位置并处理OPTIONS预检请求
Nginx中,server块的add_header会被location块内的头指令覆盖,且跨域复杂请求需要单独处理OPTIONS预检。修改后端API的server配置:server { server_name api.mywebsite.com; location / { proxy_pass http://localhost:1337; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_redirect off; # 添加上完整跨域头,加always确保错误响应也能返回头 add_header Access-Control-Allow-Origin https://panel.mywebsite.com always; add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS' always; add_header Access-Control-Allow-Headers 'Authorization, Content-Type' always; } # 直接处理OPTIONS预检请求,无需转发到后端 if ($request_method = OPTIONS) { return 204; } # 保留Certbot自动生成的SSL配置 listen [::]:443 ssl; # managed by Certbot listen 443 ssl; # managed by Certbot ssl_certificate /etc/letsencrypt/live/api.mywebsite.com/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/api.mywebsite.com/privkey.pem; # managed by Certbot include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot }关键说明
always参数:确保所有响应(包括4xx/5xx错误)都携带CORS头,避免错误场景下头丢失- OPTIONS请求处理:浏览器跨域复杂请求前会先发预检,直接返回204即可完成校验
- 允许的方法/头:可根据实际业务需求调整,比如添加自定义请求头
重启Nginx生效
执行命令验证配置并重启:sudo nginx -t && sudo systemctl reload nginx
内容的提问来源于stack exchange,提问作者firstlord

