当前位置: 首页 > 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.jsqmd.com/news/885002/

相关文章:

  • 云南高价黄金回收怎么选?2026 正规机构推荐:铭亚黄金回收 - 资讯焦点
  • 告别手动重复操作:用AutoX.js 4.1.1在雷电模拟器上搭建自动化测试环境(附Total Control投屏配置)
  • 3步打造FPS游戏AI瞄准助手:基于YOLOv5的终极解决方案
  • Taotoken用量看板如何帮助个人开发者清晰掌握API消费
  • 机器学习加速粒子物理全局拟合:XGBoust在B介子反常分析中的应用
  • 特色小吃加盟县域创业者县城开店创业查找型全攻略爆脾气生炸鸡架县域小吃加盟推荐 - 资讯焦点
  • 零基础变身黑客精英!这几个宝藏网站带你从入门到精通,速收藏!
  • 2026年专利申报避坑指南|企业高价值专利合规布局与落地实操干货 - 速递信息
  • 从‘五彩纸屑’到‘史诗魔法’:如何用Unity ParticleSystem的Noise和Trails模块提升特效质感
  • 闲置黄金变现怕被坑?认准福昌夏等六家正规平台 - 黄金上门回收
  • SingleFile:如何解决网页内容离线保存的三大痛点?
  • 2026年安徽省SCMP培训选哪家?众智商学院课程特色与真实评价 - 众智商学院课程中心
  • 特色餐饮加盟景区创业者景区开店创业购买型景区餐饮加盟项目高客流高收益全解析 - 资讯焦点
  • 【RAG】【retrievers13】相对分数融合和基于分布的分数融合
  • 如何免费快速转换B站m4s缓存文件:开源工具的完整操作指南
  • Tigerobo虎博科技:AI时代GEO服务商的确定性首选! - 资讯焦点
  • Esp32Robot入门14-系统联调与报错排查宝典(避坑宝典:声音断断续续、配网失败、API超时常见Bug排查)
  • 告别手动抢茅台!3分钟部署i茅台自动预约系统终极指南
  • 如何零基础搭建专属原神私服:KCN-GenshinServer的图形化革命
  • 从零到一:手把手教你用Playwright+Pytest+Allure搭建数据驱动的UI自动化测试(含Yaml配置详解)
  • 深圳翻译公司推荐:2026年专业语言服务商权威盘点 - 资讯焦点
  • AutoClicker实战指南:Windows鼠标点击自动化的高效解决方案
  • AVR定时器PWM驱动WS2812B:汇编级精准时序控制实战
  • 3大核心功能解析:HS2-HF Patch如何彻底改变Honey Select 2游戏体验
  • 终极Windows视频渲染器指南:如何用MPC Video Renderer实现影院级播放效果
  • 5分钟上手!UniversalUnityDemosaics:一键去除Unity游戏马赛克的终极指南 [特殊字符]
  • 2026年二氧化碳/氮气/液氮/氩气厂家怎么选?一份基于供应能力与合规底层的参考清单 - 深度智识库
  • Proteus仿真进阶:给你的AT89C52温控风扇加上OLED显示和手机蓝牙遥控
  • m4s-converter:三分钟学会B站缓存视频转换,永久保存你的珍贵收藏
  • 2026 广东省私密用品产业:领跑全国全链条发展,交悦成全国商家合作优选 - 资讯焦点