当前位置: 首页 > article >正文

理解跨域及 Nginx 解决跨域的配置详解

理解跨域及 Nginx 解决跨域的配置详解

在前后端分离的开发中,跨域问题是我们经常遇到的坑之一。很多新手开发者第一次接触到跨域时,可能会感到困惑:“为什么我的前端请求明明写得没问题,却总是报错?”今天我们就来聊聊什么是跨域、为什么会有跨域问题,以及如何通过 Nginx 配置来优雅地解决它。


什么是跨域?

跨域(Cross-Origin Resource Sharing, CORS) 是指浏览器阻止从一个域名下的网页向另一个域名发起请求的一种安全机制。简单来说,如果你的前端页面运行在 http://example.com,但后端接口的地址是 http://api.example.com,这时就属于跨域请求。

什么样的请求算跨域?

如果以下任一项不同,就算是跨域请求:

  1. 协议(http 和 https 是不同的协议)
  2. 域名(如 example.comapi.example.com
  3. 端口(如 http://example.com:8080http://example.com:3000

为什么会有跨域限制?

跨域问题是浏览器的同源策略(Same-Origin Policy)引起的。同源策略是浏览器的一种安全机制,目的是为了防止恶意网站窃取用户的敏感数据。

但是在实际开发中,前端和后端分开部署非常普遍,跨域访问几乎不可避免。那么,如何优雅地解决这个问题呢?答案就是 CORS


CORS 是如何解决跨域的?

CORS(跨域资源共享)是一种让服务端声明哪些资源可以被哪些源访问的机制。浏览器在发送跨域请求前,会先发起一个 预检请求(Preflight Request),询问服务器是否允许跨域。

常见的 CORS 响应头

服务端通过设置以下 HTTP 响应头来控制跨域访问:

  1. Access-Control-Allow-Origin
    指定允许访问资源的域。例如:* 表示允许所有域访问,https://example.com 表示仅允许特定域访问。

  2. Access-Control-Allow-Methods
    指定允许的 HTTP 方法,例如:GET, POST, PUT, DELETE

  3. Access-Control-Allow-Headers
    指定允许的自定义请求头,例如:Authorization, Content-Type

  4. Access-Control-Allow-Credentials
    指定是否允许发送凭据(如 Cookies)。值为 true 时表示允许。

  5. Access-Control-Max-Age
    指定预检请求的结果缓存时间(单位:秒)。


如何通过 Nginx 配置解决跨域?

Nginx 是我们常用的反向代理工具,也是解决跨域问题的利器。下面我们具体看看如何通过 Nginx 配置来应对跨域。

1. 简单的跨域配置

如果你的需求是让所有前端页面都可以访问后端接口,可以配置如下:

server {
    listen 80;
    server_name api.example.com;

    location / {
        add_header Access-Control-Allow-Origin *;
        add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
        add_header Access-Control-Allow-Headers Content-Type,Authorization;
        add_header Access-Control-Allow-Credentials true;
        
        if ($request_method = 'OPTIONS') {
            return 204;
        }

        proxy_pass http://backend_service;
    }
}

说明:

  • Access-Control-Allow-Origin *:允许所有域名访问。
  • Access-Control-Allow-Methods:指定支持的请求方法。
  • Access-Control-Allow-Headers:允许的自定义请求头,比如 Content-TypeAuthorization
  • Access-Control-Allow-Credentials:允许发送 Cookies 和 HTTP 认证信息。
  • OPTIONS 请求处理:浏览器的预检请求是 OPTIONS 请求,返回 204 表示成功。

2. 限制特定域名的跨域访问

如果你只希望特定域名可以访问,可以这样配置:

server {
    listen 80;
    server_name api.example.com;

    location / {
        set $cors_origin "";
        if ($http_origin = "http://frontend.example.com") {
            set $cors_origin "http://frontend.example.com";
        }

        add_header Access-Control-Allow-Origin $cors_origin;
        add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
        add_header Access-Control-Allow-Headers Content-Type,Authorization;
        add_header Access-Control-Allow-Credentials true;

        if ($request_method = 'OPTIONS') {
            return 204;
        }

        proxy_pass http://backend_service;
    }
}

说明:

  • $http_origin 是浏览器发送的请求头中的 Origin 值。
  • 通过判断 $http_origin,动态设置允许的域名。

3. 配置允许 Cookies 的跨域

如果需要支持跨域时携带 Cookies,需要同时配置服务端和前端。

Nginx 配置:

server {
    listen 80;
    server_name api.example.com;

    location / {
        add_header Access-Control-Allow-Origin http://frontend.example.com;
        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://backend_service;
    }
}

前端配置:
在 Axios 或 Fetch 请求中加上 withCredentials: true

axios.get('http://api.example.com/data', {
    withCredentials: true
});

实际场景案例

1. 前端本地开发

场景:前端通过 localhost:3000 访问后端的 api.example.com

Nginx 配置:

server {
    listen 80;
    server_name api.example.com;

    location / {
        add_header Access-Control-Allow-Origin http://localhost:3000;
        add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
        add_header Access-Control-Allow-Headers Content-Type,Authorization;
        add_header Access-Control-Allow-Credentials true;

        if ($request_method = 'OPTIONS') {
            return 204;
        }

        proxy_pass http://backend_service;
    }
}

总结

通过本文,我们了解了跨域的原理和 CORS 的基本概念,并学习了如何通过 Nginx 配置解决跨域问题。无论是简单的全局开放,还是动态控制特定域名、支持 Cookies 的跨域,都可以通过灵活的 Nginx 配置来实现。

跨域问题看似棘手,其实只要理解其原理,就不难解决。如果你还有什么疑问或想分享自己的经验,欢迎留言讨论! 😊


http://www.kler.cn/a/520485.html

相关文章:

  • 【MySQL — 数据库增删改查操作】深入解析MySQL的 Retrieve 检索操作
  • 第26篇 基于ARM A9处理器用C语言实现中断<二>
  • 从零开始开发纯血鸿蒙应用之自定义构建函数
  • wordpress被挂码的原因
  • 论文阅读(六):利用基因型信息作为学习基因网络的先验知识
  • 【leetcode100】从前序与中序遍历序列构造二叉树
  • 二级C语言题解:孤独数、找最长子串、返回两数组交集
  • 每日一题-判断是不是完全二叉树
  • 二叉堆--优先级队列和堆排序
  • MySQL(高级特性篇) 12 章——数据库其它调优策略
  • Flink运行时架构
  • Netty框架学习笔记
  • GPU算力平台|在GPU算力平台部署AI虚拟换衣模型(CatVTON)的应用实战教程
  • 模拟电子技术-常用半导体器件
  • RabbitMQ模块新增消息转换器
  • [MySQL]数据库的效率问题与索引的底层原理
  • 人工智能丨Midscene:让UI自动化测试变得更简单
  • 高温环境对电机性能的影响与LabVIEW应用
  • 1.27 保存和加载链表内容
  • 笔试-二维数组2