Karp 的技术博客

在前后端分离开发中,本地前端一般通过 http://localhost:3000http://localhost:5173http://localhost:8080 等地址运行,而后端接口常常部署在:

https://api.example.com

由于协议、域名或端口不同,浏览器会触发 CORS(跨域访问限制),导致接口请求报错,例如:

Access to fetch at 'https://api.example.com' from origin 'http://localhost:5173' has been blocked by CORS policy

要解决这个问题,我们可以在 Nginx 中为开发环境添加 跨域支持


✅ 正确理解:CORS 不允许写多个域名

错误写法(无效):

add_header Access-Control-Allow-Origin http://localhost:5173, http://localhost:3000;

浏览器会直接忽略,因为 Access-Control-Allow-Origin 必须只能有一个值


✅ 最佳实践:根据请求的 Origin 动态返回允许的来源

我们可以让 Nginx 判断请求的 Origin 是否在允许范围内,如果是,就把它回传给浏览器,解决跨域问题。

📦 完整可直接复制的 Nginx 配置

# 开发环境 API 代理
server {
    listen 443 ssl;
    server_name api.example.com;

    # SSL 略...

    location / {
        # 允许所有 localhost 端口
        if ($http_origin ~* "^https?://localhost(:\d+)?$") {
            add_header Access-Control-Allow-Origin $http_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 "Content-Type, Authorization, X-Requested-With";
            return 204;
        }

        proxy_pass http://backend_service;  # 你的后端服务地址
    }
}

🧠 这段配置做了哪些事?

功能说明
动态匹配 Origin只允许 http://localhost:* 发请求
支持携带 Cookie / TokenAccess-Control-Allow-Credentials: true
支持预检(OPTIONS)请求防止跨域被浏览器拦截
不影响生产环境可只在开发环境使用

✅ 前端使用时记得加 withCredentials(如果你传 Cookie)

fetch("https://api.example.com/user/info", {
  credentials: "include"
});

如果你用 axios:

axios.defaults.withCredentials = true;

🔒 安全提示(非常重要)

  • 仅在开发环境允许 $http_origin
  • 生产环境一定要写死域名,例如:
add_header Access-Control-Allow-Origin https://www.yourwebsite.com;

否则会有 安全风险


🎯 总结

场景解决方案
本地开发跨域使用 $http_origin 动态回源
不同端口需要访问接口正则匹配 localhost
正式环境固定域名,禁止动态 CORS

nginx

版权属于:karp
作品采用:本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。
更新于: 2025年11月07日 07:12
0

目录

来自 《解决本地开发跨域问题:如何配置 Nginx 允许 `localhost` 调用后端接口》