Nginx 配置跨域的实现及常见问题解决

2025-06-17 16:50

本文主要是介绍Nginx 配置跨域的实现及常见问题解决,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《Nginx配置跨域的实现及常见问题解决》本文主要介绍了Nginx配置跨域的实现及常见问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来...

1. 跨域

1.1 同源策略

同源策略(Same-Origin Policy)是浏览器的一种安全机制,它限制了不同源之间的资源共享。两个 URL 被认为是同源的,必须满足以下三个条件:

  • 协议相同(如 http 或 https)
  • 域名相同
  • 端口相同

例如:

  • 同源:
    • http://example.com:8080 和 http://example.com:8080
  • 跨域:
    • http://example.com:8080 和 http://example.com:3000(端口不同)
    • http://example.com 和 https://example.com(协议不同)
    • http://example.com 和 http://api.example.com(域名不同)

1.2 跨域资源共享(CORS)

CORS 是一种机制,通过设置特定的 HTTP 响应头,允许浏览器访问跨域资源。CORS 头主要包括:

  • **Access-Control-Allow-Origin**:指定允许访问的源。
  • **Access-Control-Allow-Methods**:指定允许的 HTTP 方法(如 GET, POST)。
  • **Access-Control-Allow-Headers**:指定允许的请求头(如 Content-Type, Authorization)。
  • **Access-Control-Allow-Credentials**:是否允许携带 Cookie 或其他凭证。
  • **Access-Control-Max-Age**:预检请求的缓存时间。

2. Nginx 配置跨域的场景

2.1 场景 1:简单跨域请求

如果前端发送的是 简单请求(如 GET 或 POST,且没有自定义请求头),Nginx 只需要在响应中添加跨域头即可。

2.2 场景 2:复杂跨域请求

如果前端发送的是 复杂请求(如 POST 请求包含 Content-Type: application/json 或自定义头 Authorization 等),浏览器会先发起 预检请求(OPTIONS),询问服务器是否允许跨域。

Nginx 必须正确处理 OPTIONS 请求,并返回所有必要的跨域头。

3. Nginx 配置跨域的完整实现

3.1 基础跨域配置

基础的 Nginx 跨域配置示例:

server {
  listen 8081;
  server_name localhost;

  # 根目录(H5 前端文件)
  root /usr/share/nginx/html/applet/dist/build/h5/;

  # 跨域配置
  location /api/ {
    # 添加跨域头
    add_header 'Access-Control-Allow-Origin' '*' always;
    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
    add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Requested-With' always;
    add_header 'Access-Control-Allow-Credentials' 'true' always;

    # 如果是预检请求 (OPTIONS),直接返回成功
    if ($request_method = 'OPTIONS') {
      add_header 'Access-Control-Allow-Origin' '*' always;
      add_header 'Access-Control-Allow-Methods' 'GET, POST, dwrdoIoPiXOPTIONS, PUT, DELETE';
      add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Requested-With';
      add_header 'Access-Control-Max-Age' 1800;
      add_header 'Content-Length' 0;
      add_header 'Content-Type' 'text/plain';
      return 204;
    }

    # 反向代理到后端服务
    proxy_pass url; # 替换为后端服务地址
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  }
}

3.2 配置解析

  • Access-Control-Allow-Origin:允许的跨域来源。如果后端需要支持多个来源,可以动态设置该值;或者使用 * 表示允许所有来源。
  • Access-Control-Allow-Methods:声明支持的 HTTP 方法。
  • Access-Control-Allow-Headers:声明允许的自定义请求头。如果前端发送了 Authorization 或其他自定义头,必须在这里明确声明。
  • Access-Control-Max-Age:指定预检请求的缓存时间,单位为秒(如 1800 表示缓存 30 分钟)。
  • if ($request_method = 'OPTIONS'):单独处理预检请求,直接返回 204,避免请求被转发到后端。
  • 在 if 判断中直接返回响应(如 return 204)的情况下,add_header** 需要在同一个 if 块内声明**,否则不会被应用到响应中。这里主要是nginx的响应流程和作用域特性。

3.3 动态配置跨域来源

3.3.1 常规配置

如果后端需要允许多个特定来源,可以通过 $http_origin 动态设置 Access-Control-Allow-Origin:

location /api/ {
  # 动态设置跨域来源
  set $cors "";
  if ($http_origin ~* (http://ip:port|http://example.com)) {
    set $cors $http_origin;
  }

  add_header 'Access-Control-Allow-Origin' $cors always;
  add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
  add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Requested-With' always;
  add_header 'Access-Control-Allow-Credentials' 'true' always;

  # 如果是预检请求 (OPTIONS),直接返回成功
  if ($rDWrdoIoPiXequest_method = 'OPTIONS') {
    add_header 'Access-Control-Allow-Origin' $cors always;
    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
    add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Requested-With';
    add_header 'Access-Control-Max-Age' 1800;
    add_header 'Content-Length' 0;
    add_header 'Content-Type' 'text/plain';
    return 204;
  }

  proxy_pass bakcendurl;
}

3.3.2 进阶配置

Nginx 提供了 map指令,可用于根据请求条件动态设置变量。利用map指令提前设置变量,避免 if 指令的复杂嵌套,更安全地实现动态跨域逻辑。

# 动态设置允许的跨域来源
map $http_origin $cors_origin {
    default "";
    "~^https?://trusteddomain1\.com$" $http_origin;
    "~^https?://trusteddomain2\.com$" $http_origin;
}

# 动态设置缓存时间
map $http_origin $cors_max_age {
    default "0";
    "~^https?://trusteddomain1\.com$" "86400"; # 1 天
    "~^https?://trusteddomain2\.com$" "3600";  # 1 小时
}

server {
    listen 8081;
    server_name localhost;

    location ~* ^/(url|url1|……) {
        add_header 'Access-Control-Allow-Origin' "$cors_origin" always;
        add_header 'Vary' 'Origin' always;
       	add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
       	add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Requested-With' always;
		add_header 'Access-Control-Max-Age' "$cors_max_age" always; 

        # 特殊处理 OPTIONS 预检请求
        if ($request_method = 'OPTIONS') {
			# 设置 CORS 响应头
       		add_header 'Access-Control-Allow-Origin' "$cors_origin" always;
       		add_header 'Vary' 'Origin' always;
       		add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
       		add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Requested-With' always;
			add_header 'Access-Control-Max-Age' "$cors_max_age" always; 

            add_header 'Content-Length' '0' always;
            add_header 'Content-Type' 'text/plain' always;
            return 204;
        }

        # 其他请求正常代理到后端服务
        proxy_pass backendurl;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        client_max_body_size 1024m;
        proxy_buffer_size 1024k;
        proxy_buffers 16 1024k;
        proxy_busy_buffers_size 2048k;
        proxy_temp_file_write_size 2048k;
    }
}

测试命令:

curl -X OPTIONS http://localhost:8081/api/test \
-H "Content-Type: application/json" \
-H "Origin: https://trusteddomain1.com" \
-H "Authorization: Bearer null" \
-I

结果:

Nginx 配置跨域的实现及常见问题解决

改为第二个域名,输出结果:

Nginx 配置跨域的实现及常见问题解决

配置成功。

4. 验证跨域配置是否生效

4.1 使用 curl 验证

预检请求

运行以下命令,检查 OPTIONS 请求的响应头是否包含正确的跨域头:

curl -X OPTIONS http://localhost:8081/api/test-endpoint \
-H "Origin: yoururl" \
-H "Access-Control-Request-Method: POST" \
-H "Access-Control-Request-Headers: Content-Type, Authorization" -I

实际请求

运行以下命令,检查实际请求的跨域头:

curl -X POST http://localhost:8081/api/test-endpoint \
-H "Origin: yoururl" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{"key":"value"}' -I

将Origin的值替换即可。

5. 常见问题及DWrdoIoPiX解决方法

5.1 No 'Access-Control-Allow-Origin' header is present on the requested resource

  • 原因:后端未返回 Accesshttp://www.chinasem.cn-Control-Allow-Origin。
  • 解决:检查 Nginx 或后端服务是否返回了正确的跨域头。

5.2 Request header field <header_name> is not allowed by Access-Control-Allow-Headers

  • 原因:前端发送了未被允许的自定义请求头。
  • 解决:在 Access-Control-Allow-Headers 中添加该头(如 Authorization, channel 等)。

5.3 OPTIONS 请求返回 404 或 405

  • 原因:Nginx 或后端未正确处理 OPTIONS 请求。
  • 解决:在 Nginx 配置中使用 if ($request_method = 'OPTIONS') 单独处理预检请求。

6. 注意事项

(1) 不建议长期使用通配符 *

  • 如果前端需要发送 Authorization 或 Cookie,不能使用通配符 *,需要指定具体的跨域来源:
add_header 'Access-Control-Allow-Origin' 'http://ip:port' always;
add_header 'Access-Control-Allow-Credentials' 'true' always;

(2) 确保前端请求头与后端配置匹配

  • 如果前端发送了自定义头(如 channel),后端的 Access-Control-Allow-Headers 必须包含这些头。

(3) 确保后端不会覆盖 Nginx 的跨域头

  • 如果后端服务也返回了跨域头,可能会覆盖 Nginx 的配置。可以通过 proxy_hide_header 移除后端返回的头:
proxy_hide_header Access-Control-Allow-Origin;
proxy_hide_hpythoneader Access-Control-Allow-Methods;
proxy_hide_header Access-Control-Allow-Headers;

7. 总结

  • CORS 的核心在于配置正确的跨域头(Access-Control-Allow-*)。
  • Nginx 配置跨域的关键点:
    • 处理预检请求(OPTIONS)。
    • 添加必要的跨域头(Access-Control-Allow-Origin, Access-Control-Allow-Headers 等)。
    • 确保跨域头在所有响应中生效(使用 always 参数)。
  • 使用工具(如 curl 或浏览器开发者工具)验证跨域配置是否正确。

到此这篇关于Nginx 配置跨域的实现及常见问题解决的文章就介绍到这了,更多相关Nginx 配置跨域内容请搜索China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程China编程(www.chinasem.cn)!

这篇关于Nginx 配置跨域的实现及常见问题解决的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1155102

相关文章

MySQL数据库双机热备的配置方法详解

《MySQL数据库双机热备的配置方法详解》在企业级应用中,数据库的高可用性和数据的安全性是至关重要的,MySQL作为最流行的开源关系型数据库管理系统之一,提供了多种方式来实现高可用性,其中双机热备(M... 目录1. 环境准备1.1 安装mysql1.2 配置MySQL1.2.1 主服务器配置1.2.2 从

C++中unordered_set哈希集合的实现

《C++中unordered_set哈希集合的实现》std::unordered_set是C++标准库中的无序关联容器,基于哈希表实现,具有元素唯一性和无序性特点,本文就来详细的介绍一下unorder... 目录一、概述二、头文件与命名空间三、常用方法与示例1. 构造与析构2. 迭代器与遍历3. 容量相关4

C++中悬垂引用(Dangling Reference) 的实现

《C++中悬垂引用(DanglingReference)的实现》C++中的悬垂引用指引用绑定的对象被销毁后引用仍存在的情况,会导致访问无效内存,下面就来详细的介绍一下产生的原因以及如何避免,感兴趣... 目录悬垂引用的产生原因1. 引用绑定到局部变量,变量超出作用域后销毁2. 引用绑定到动态分配的对象,对象

SpringBoot基于注解实现数据库字段回填的完整方案

《SpringBoot基于注解实现数据库字段回填的完整方案》这篇文章主要为大家详细介绍了SpringBoot如何基于注解实现数据库字段回填的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解... 目录数据库表pom.XMLRelationFieldRelationFieldMapping基础的一些代

Java HashMap的底层实现原理深度解析

《JavaHashMap的底层实现原理深度解析》HashMap基于数组+链表+红黑树结构,通过哈希算法和扩容机制优化性能,负载因子与树化阈值平衡效率,是Java开发必备的高效数据结构,本文给大家介绍... 目录一、概述:HashMap的宏观结构二、核心数据结构解析1. 数组(桶数组)2. 链表节点(Node

Java AOP面向切面编程的概念和实现方式

《JavaAOP面向切面编程的概念和实现方式》AOP是面向切面编程,通过动态代理将横切关注点(如日志、事务)与核心业务逻辑分离,提升代码复用性和可维护性,本文给大家介绍JavaAOP面向切面编程的概... 目录一、AOP 是什么?二、AOP 的核心概念与实现方式核心概念实现方式三、Spring AOP 的关

Nginx分布式部署流程分析

《Nginx分布式部署流程分析》文章介绍Nginx在分布式部署中的反向代理和负载均衡作用,用于分发请求、减轻服务器压力及解决session共享问题,涵盖配置方法、策略及Java项目应用,并提及分布式事... 目录分布式部署NginxJava中的代理代理分为正向代理和反向代理正向代理反向代理Nginx应用场景

Nginx搭建前端本地预览环境的完整步骤教学

《Nginx搭建前端本地预览环境的完整步骤教学》这篇文章主要为大家详细介绍了Nginx搭建前端本地预览环境的完整步骤教学,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录项目目录结构核心配置文件:nginx.conf脚本化操作:nginx.shnpm 脚本集成总结:对前端的意义很多

IDEA和GIT关于文件中LF和CRLF问题及解决

《IDEA和GIT关于文件中LF和CRLF问题及解决》文章总结:因IDEA默认使用CRLF换行符导致Shell脚本在Linux运行报错,需在编辑器和Git中统一为LF,通过调整Git的core.aut... 目录问题描述问题思考解决过程总结问题描述项目软件安装shell脚本上git仓库管理,但拉取后,上l

Python实现字典转字符串的五种方法

《Python实现字典转字符串的五种方法》本文介绍了在Python中如何将字典数据结构转换为字符串格式的多种方法,首先可以通过内置的str()函数进行简单转换;其次利用ison.dumps()函数能够... 目录1、使用json模块的dumps方法:2、使用str方法:3、使用循环和字符串拼接:4、使用字符