前端CORS场景与解决方案

跨源资源共享(Cross-Origin Resource Sharing,简称CORS,或通俗地译为跨域资源共享)是一种基于 HTTP 头的机制,该机制通过允许服务器标示除了它自己以外的其他(域、协议或端口),使得浏览器允许这些源访问加载自己的资源。跨源资源共享还通过一种机制来检查服务器是否会允许要发送的真实请求,该机制通过浏览器发起一个到服务器托管的跨源资源的“预检”请求。在预检中,浏览器发送的头中标示有 HTTP 方法和真实请求中会用到的头。

CORS 常见场景

  1. 开发环境下的前后端联调

    • 前端开发时,本地开发服务器(如 localhost:3000)需要访问后端 API(如 api.example.com),此时浏览器会因同源策略限制而拒绝请求。
  2. 前后端分离部署

    • 前端和后端部署在不同的域名或子域名下(如前端在 web.example.com,后端在 api.example.com),跨域请求会触发 CORS 问题。
  3. 使用第三方 API

    • 当前端应用需要调用第三方服务(如 api.thirdparty.com)时,如果第三方服务未正确配置 CORS,请求会被浏览器拦截。
  4. 复杂请求的预检失败

    • 对于非简单请求(如使用 PUTDELETE 方法,或带有自定义请求头的 POST 请求),浏览器会先发送一个 OPTIONS 预检请求,如果服务器未正确响应预检请求,实际请求将无法执行。

CORS 解决方案

1. 服务器端配置

  • 设置响应头:在服务器端配置 Access-Control-Allow-Origin,允许特定域名或所有域名访问资源。例如:

    1
    Access-Control-Allow-Origin: https://example.com

    或者允许所有来源:

    1
    Access-Control-Allow-Origin: *

    同时,可以设置其他相关头信息,如 Access-Control-Allow-MethodsAccess-Control-Allow-Headers,以支持特定的 HTTP 方法和请求头。

  • 处理预检请求:对于复杂请求,服务器需要正确响应 OPTIONS 预检请求,返回允许的跨域配置信息。

  • 示例代码(Node.js + Express):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    const express = require('express');
    const app = express();

    app.use((req, res, next) => {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
    res.header('Access-Control-Allow-Headers', 'Content-Type');
    if (req.method === 'OPTIONS') {
    res.sendStatus(200);
    } else {
    next();
    }
    });

    app.get('/api/data', (req, res) => {
    res.json({ message: 'Hello, CORS!' });
    });

    app.listen(3000, () => {
    console.log('Server running on port 3000');
    });

2. 前端代理

  • 使用 Webpack 开发服务器:在开发环境中,可以通过 Webpack 的 devServer.proxy 配置,将跨域请求代理到目标服务器。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    // webpack.config.js
    devServer: {
    proxy: {
    "/api": {
    target: "http://api.example.com",
    changeOrigin: true,
    },
    },
    }
  • 使用 Nginx 代理:在生产环境中,可以通过 Nginx 配置反向代理,将前端请求转发到后端服务。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    server {
    listen 80;
    server_name example.com;

    location /api {
    proxy_pass http://api.example.com;
    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_set_header X-Forwarded-Proto $scheme;
    }
    }

3. 其他技术手段

  • JSONP:适用于仅支持 GET 请求的简单跨域场景,但不支持现代的 POST 或其他复杂请求。
  • Service Worker:通过在前端配置 Service Worker 拦截请求并处理跨域问题。

注意事项

  1. 安全性:避免在生产环境中使用 Access-Control-Allow-Origin: *,建议明确指定允许的域名。
  2. 调试工具:使用浏览器开发者工具查看网络请求和响应头,确认 CORS 配置是否生效。
  3. 前后端协作:CORS 问题需要前后端共同协作解决,前端开发者应与后端团队密切沟通。

通过以上方法,可以有效解决前端开发中的 CORS 问题,确保应用的正常运行和数据交互。