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

Nginx解决跨域问题

Nginx解决跨域问题

一、跨域原理与解决思路

什么是跨域

跨域是浏览器的安全策略,当页面脚本试图访问不同源(协议、域名、端口任一不同)的资源时,浏览器会拦截请求。

关键点:跨域限制只存在于浏览器中。使用curlPostman或服务端HttpClient发起请求完全不受影响,因为它们没有同源策略。

核心解决思路

既然跨域是浏览器基于地址判断的,解决思路就是:

让浏览器认为所有请求都来自同一个源——保持浏览器地址栏中的协议、域名、端口一致即可。

具体做法是通过反向代理(Nginx),将前端页面和后端服务统一代理到同一个地址下,浏览器看到的始终是同一个 origin。

二、常见问题:iframe 跨域无法操作登录表单

问题场景

在 SSO 集成中,一种常见方案是用 iframe 内嵌第三方登录页,然后通过 JS 自动填充用户名密码并提交登录:

<iframesrc="http://sso-server:8080/login"id="loginFrame"></iframe><script>constiframe=document.getElementById('loginFrame');iframe.onload=function(){// 尝试获取 iframe 内部 DOM 并填充表单constiframeDoc=iframe.contentDocument;constusernameInput=iframeDoc.querySelector('input[type="text"]');constpasswordInput=iframeDoc.querySelector('input[type="password"]');usernameInput.value='admin';// 报错!passwordInput.value='password';// 报错!};</script>

报错信息

Uncaught DOMException: Blocked a frame with origin "http://my-app:3000" from accessing a cross-origin frame.

原因分析

浏览器禁止跨域访问 iframe 内部的 DOM。当父页面(http://my-app:3000)和 iframe 页面(http://sso-server:8080)不同源时,父页面的 JS 无法:

  • 读取或修改 iframe 内的 DOM 元素
  • 获取 iframe 内的 Cookie 或 LocalStorage
  • 监听 iframe 内的事件

这意味着通过 iframe 内嵌登录页 + JS 自动填充的方案在跨域场景下行不通。

三、使用中转页 + Nginx 解决跨域

解决方案架构

核心思路:将中转页地址登录服务后端代理到同一个域名和端口下,让浏览器认为它们是同源的。

用户浏览器 │ ▼ Nginx (统一入口 http://proxy-server:80) ├── /sso-proxy/ → 中转页服务 (http://127.0.0.1:8081) ├── /app/ → 目标系统前端 (http://127.0.0.1:3000) └── /app-api/ → 目标系统后端 API (http://127.0.0.1:8080)

浏览器始终访问http://proxy-server,所有请求同源,跨域问题消失。

Nginx 配置示例

server { listen 80; server_name proxy-server; # 中转页(SSO 登录中转服务) location /sso-proxy/ { proxy_pass http://127.0.0.1:8081/sso-proxy/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } # 目标系统前端 location /app/ { proxy_pass http://127.0.0.1:3000/app/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } # 目标系统后端 API location /app-api/ { proxy_pass http://127.0.0.1:8080/app-api/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; # 设置 CORS 头部,允许中转页访问 add_header Access-Control-Allow-Origin $http_origin; add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"; add_header Access-Control-Allow-Headers "Content-Type, Authorization, X-Requested-With"; add_header Access-Control-Allow-Credentials true; # 处理预检请求 if ($request_method = 'OPTIONS') { add_header Access-Control-Allow-Origin $http_origin; add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"; add_header Access-Control-Allow-Headers "Content-Type, Authorization, X-Requested-With"; add_header Access-Control-Allow-Credentials true; add_header Content-Length 0; return 204; } } }

CORS 头部注意事项:只能设置一次

Access-Control-Allow-Origin响应头只能出现一次。如果 Nginx 和后端应用同时设置了该头部,浏览器会收到重复的头部导致请求失败:

Access to XMLHttpRequest has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header contains multiple values 'http://my-app, http://my-app', but only one is allowed.

解决办法:只在一处设置 CORS 头部。

  • 方案 A:只在 Nginx 设置,后端不设置
  • 方案 B:只在后端设置,Nginx 不加add_header

如果后端已经设置了 CORS 头,Nginx 中可以用proxy_hide_header去掉后端返回的头,再由 Nginx 统一设置:

location /app-api/ { proxy_pass http://127.0.0.1:8080/app-api/; # 去掉后端返回的 CORS 头,避免重复 proxy_hide_header Access-Control-Allow-Origin; proxy_hide_header Access-Control-Allow-Methods; proxy_hide_header Access-Control-Allow-Headers; proxy_hide_header Access-Control-Allow-Credentials; # 由 Nginx 统一设置 add_header Access-Control-Allow-Origin $http_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; }

中转页工作流程

完整的 SSO 中转登录流程如下:

1. 用户访问中转页 http://proxy-server/sso-proxy/transit.html?token=xxx 2. 中转页通过同源的 API 获取用户信息 GET http://proxy-server/sso-proxy/getUserInfo (同源,无跨域问题) 3. 中转页内嵌 iframe 加载目标系统 iframe src = http://proxy-server/app/ (同源,可以操作 iframe DOM) 4. 中转页填充用户名密码并调用登录接口 POST http://proxy-server/app-api/user/login (同源,无跨域问题) 5. 登录成功,跳转到目标系统 redirect → http://proxy-server/app/#/home

四、其他补充方案:Token 重定向

当内外网环境无法通过 Nginx 统一代理时(如内网系统需要从外网 SSO 获取认证),可以使用Token 重定向方案:

  1. 用户在外网 SSO 完成认证,获取 Token
  2. SSO 将用户重定向到内网中转页,URL 中携带 Token
  3. 中转页从 URL 提取 Token,再重定向到目标系统
外网 SSO 认证 │ ▼ 重定向(携带 token) http://内网地址/sso-proxy/transit.html?redirect=目标地址&token=xxx │ ▼ 中转页提取 token,拼接后跳转 http://目标系统地址?token=xxx

这种方式避免了跨域 Ajax 请求,通过浏览器地址栏跳转传递 Token,不受同源策略限制。

五、总结

方案适用场景优点缺点
Nginx 反向代理所有服务可统一入口彻底解决跨域,对代码无侵入需要 Nginx 配置
CORS 头部服务端可控配置灵活注意不能重复设置
Token 重定向内外网隔离场景绕过跨域限制流程较复杂
iframe + 同源代理需要操作第三方页面 DOM可自动填充表单必须保证同源

最佳实践:优先使用 Nginx 反向代理将所有服务统一到同一域下,从根本上消除跨域问题。在无法统一代理的场景下,使用 Token 重定向作为补充方案。

http://www.zskr.cn/news/1381920.html

相关文章:

  • Taotoken用量看板如何帮助个人开发者清晰掌握API消费
  • 机器学习加速粒子物理全局拟合:XGBoust在B介子反常分析中的应用
  • 猫抓浏览器扩展终极指南:5分钟掌握全网视频资源下载技巧
  • ArduPilot飞行模式实战:从代码角度看Stabilize、Acro、Loiter模式如何切换(附避坑指南)
  • SingleFile:如何解决网页内容离线保存的三大痛点?
  • 2026年专利申报避坑指南|企业高价值专利合规布局与落地实操干货 - 速递信息
  • 闲置黄金变现怕被坑?认准福昌夏等六家正规平台 - 黄金上门回收
  • Jetson Orin上TVA模型DLA精准卸载配置
  • 从科研图表到商业报表:如何用Matplotlib的legend()提升你的图表专业度?
  • 免费鼠标连点器MouseClick:终极自动化解决方案,3分钟解放你的双手
  • Cesium动态数据可视化实战:CallbackProperty结合setInterval打造实时运动轨迹
  • 2026 广东省私密用品产业:领跑全国全链条发展,交悦成全国商家合作优选 - 资讯焦点
  • 【求职】换工作时的五种语言和7个阶段
  • 2026自媒体运营必看:十大图片素材网站推荐,配图效率翻倍 - 品牌2025
  • FeHelper:从工具集合到开发效能平台的架构演进
  • 运维老鸟的私藏技巧:用Ventoy在Linux服务器上批量制作Windows安装盘
  • 微信红包助手终极指南:无需ROOT的智能抢红包解决方案
  • 【Sora 2 MOV导出终极指南】:20年视频引擎专家亲授3步绕过官方限制,实测帧率/色彩/元数据零损耗
  • 收藏!2026年大模型行业爆发,小白程序员黄金入局期,薪资暴涨必看
  • Apache Commons FileUpload CVE-2025-48976:multipart解析器状态机崩塌漏洞深度解析
  • 中小企无需重型数据中台:轻量化数据体系搭建完整方案
  • 2026年资质齐全的炸鸡小吃加盟品牌排名 - 资讯焦点
  • ComfyUI-Manager完全指南:掌握AI工作流管理的核心技术
  • Python strip 与 rstrip 函数区别
  • OpenHRMS:如何用开源方案解决中小企业人力资源管理难题?
  • 3步设置解放双手!AzurLaneAutoScript碧蓝航线自动化脚本终极使用指南
  • mybatis执行流程、关联映射、注解开发
  • 别再死记硬背了!用IDEF1x的‘标定’与‘非标定’联系,轻松搞定数据库设计中的主外键关系
  • 在 Hermes Agent 项目中配置自定义模型提供商指向 Taotoken 服务
  • VS2022+QT使用claudecode