Sa-Token 反向代理 URI 丢失问题排查与解决:`getUrl()` 原理及 curr-domain 配置实战

发布时间:2026/9/14 0:18:24

Sa-Token 反向代理 URI 丢失问题排查与解决:`getUrl()` 原理及 curr-domain 配置实战 Sa-Token 反向代理 URI 丢失问题排查与解决getUrl()原理及 curr-domain 配置实战【免费下载链接】Sa-Token✨ 开源、免费、一站式 Java 权限认证框架让鉴权变得简单、优雅—— 登录认证、权限认证、分布式 Session 会话、微服务网关鉴权、SSO 单点登录、OAuth2.0 统一认证、jwt 集成、API Key 秘钥授权、API 参数签名项目地址: https://gitcode.com/GitHub_Trending/sa/Sa-Token导读在 Java Web 项目中使用 Nginx 反向代理后SaHolder.getRequest().getUrl()获取到的地址常常与用户浏览器中实际访问的地址不一致域名、端口或路径前缀丢失进而导致 Sa-Token 的 SSO 单点登录等依赖真实访问地址的功能异常。本文以 Sa-Token 框架源码为线索剖析getUrl()的底层实现原理并给出两种官方推荐解决方案Nginx 追加 header 重写 SaRequest 创建策略与配置sa-token.curr-domain读完即可在真实项目中落地修复。一、问题背景为什么反向代理会弄丢URI1.1getUrl()的底层实现Sa-Token 通过SaHolder.getRequest()获取当前请求的包装对象其中getUrl()方法用于获取当前程序所在外网的访问地址不带 query 参数。从源码接口定义看// cn.dev33.satoken.context.model.SaRequest /** * 返回当前请求的url不带query参数例http://xxx.com/test */ String getUrl();接口定义见 SaRequest.java。在 Servlet 环境下其默认实现位于 SaRequestForServlet.java代码如下public String getUrl() { String currDomain SaManager.getConfig().getCurrDomain(); if( ! SaFoxUtil.isEmpty(currDomain)) { return currDomain this.getRequestPath(); } return request.getRequestURL().toString(); }可以看到默认逻辑直接调用 Servlet 原生的request.getRequestURL().toString()。也就是说Sa-Token 的getUrl()最终依赖 Servlet 容器提供的请求信息。1.2 依赖getUrl()的核心模块框架内很多模块都用到了这个能力最典型的就是SSO 单点登录客户端。在 SaSsoClientProcessor.java 中构建 SSO 认证中转地址时// 获取当前项目的 sso 登录中转页地址形如http://sso-client.com/sso/login // 全局配置了就是用全局的否则使用当前请求的地址 String currSsoLoginUrl cfg.getCurrSsoLogin(); if(SaFoxUtil.isEmpty(currSsoLoginUrl)) { currSsoLoginUrl SaHolder.getRequest().getUrl(); } // 构建最终授权地址 url形如http://sso-server.com/sso/auth?redirectUrlhttp://sso-client.com/sso/login?backhttp://sso-client.com String serverAuthUrl ssoClientTemplate.buildServerAuthUrl(currSsoLoginUrl, back);此处若getUrl()拿不到正确的外网地址SSO 客户端回调地址就会出错导致整个单点登录流程无法闭环。此外同一文件第 331 行 在拼接单点登出回调地址时也使用了getUrl()。1.3 复现问题我们可以编写一个简单的接口来验证当前环境下getUrl()的返回结果// 显示当前程序所在外网的访问地址 RequestMapping(test) public String test() { return 您访问的是 SaHolder.getRequest().getUrl(); }从浏览器直接访问此接口正常情况下返回的是真实外网地址形如您访问的是http://local.dev33.cn:8902/api/test然而当部署时使用 Nginx 做了一层反向代理例如将http://local.dev33.cn:8902/api代理到内网服务后由于Nginx 转发给后端服务的是内部请求地址Servlet 容器解析出的requestURL可能是内网主机、默认端口或去掉了上下文路径的地址最终结果就和我们预想的出现偏差返回的往往是http://内网IP:端口/api/test之类的内部地址甚至丢失了api路径前缀。需要特别说明不仅是 Nginx所有包含路由转发的地方都有可能导致上述丢失 uri 的现象例如网关转发、二级域名分发、负载均衡等。它们的共性是Servlet 容器拿到的原始请求信息不再等价于浏览器端的访问信息。二、解决思路从自动识别改为手动获取既然程序无法在反向代理场景下自动识别外网地址官方给出的解决思路是放弃自动推导改为手动注入真实外网地址。Sa-Token 为此提供了两种官方方案可根据项目实际情况选用。三、方案一Nginx 转发时追加 header 参数该方案分两步Nginx 侧透传外网地址程序侧重写SaRequest创建策略两步必须同步存在原因见下文安全警告。3.1 第一步Nginx 代理转发处增加 header在 Nginx 的location代理配置中增加一行proxy_set_header Public-Network-URL http://$http_host$request_uri;其原理是$http_host是 Nginx 从请求头中解析出的 Host即浏览器访问时的域名与端口$request_uri是浏览器请求的完整原始 URI包含 query 参数两者拼接即可还原用户真正访问的外网地址并通过自定义请求头Public-Network-URL传递给后端程序。3.2 第二步程序中重写 SaRequest 创建策略在 Spring Boot 项目中新建配置类通过SaStrategy.instance.setCreateSaRequest(...)重写框架创建SaRequest的策略Configuration public class SaTokenConfigure { PostConstruct public void configSaStrategy() { SaStrategy.instance.setCreateSaRequest(source - { HttpServletRequest request (HttpServletRequest) source; return new SaRequestForServlet(request) { Override public String getUrl() { String publicUrl request.getHeader(Public-Network-URL); if (publicUrl ! null) { return publicUrl; } return super.getUrl(); } }; }); } }代码要点解读SaStrategy是 Sa-Token 的策略对象统一定义了框架内的一些关键性逻辑算法方便开发者按需重写。其中createSaRequest策略负责将底层源对象这里是 Servlet 的HttpServletRequest包装为框架统一的SaRequest其默认实现会抛出NotImplException见 SaStrategy.java在 Servlet 集成环境中由 starter 提供默认包装实现。这里通过匿名子类覆写getUrl()优先读取 Nginx 传入的Public-Network-URL请求头若该请求头存在则直接返回否则回退到super.getUrl()默认逻辑。source是Object类型因此需要先强转为HttpServletRequest。setCreateSaRequest采用链式风格赋值见 SaStrategy.java返回SaStrategy自身便于集中配置。其它逻辑保持不变框架即可正确获取外网 uri 地址。3.3 风险警告步骤一与步骤二需要同步存在如果只做第二步程序读取 header而不在 Nginx 中统一注入该 header那么任意前端请求都可以假传Public-Network-URL请求头从而伪造自己的访问地址在 SSO 等对地址敏感的流程中可能引发安全风险。同理只配 Nginx 不做程序侧读取则配置无效。因此header 注入必须由可信的网关层Nginx统一完成且程序侧逻辑必须与之一一对应。四、方案二直接在 yml 中配置当前项目的网络访问地址如果项目的外网访问地址是固定不变的不涉及多域名、多环境动态切换官方提供了更简单直接的方案在application.yml中配置sa-token.curr-domain。4.1 配置示例yaml风格sa-token: # 配置当前项目的网络访问地址 curr-domain: http://local.dev33.cn:8902/apiproperties风格# 配置当前项目的网络访问地址 sa-token.curr-domainhttp://local.dev33.cn:8902/api配置完成后框架内部所有依赖getUrl()的逻辑都会以http://local.dev33.cn:8902/api作为基准地址即可避免路由转发过程中丢失 uri 的问题。4.2 配置项源码解析curr-domain是SaTokenConfig中的核心配置字段之一源码定义如下见 SaTokenConfig.java/** * 配置当前项目的网络访问地址 */ private String currDomain;其在getUrl()中的实际生效逻辑见 SaRequestForServlet.java为String currDomain SaManager.getConfig().getCurrDomain(); if( ! SaFoxUtil.isEmpty(currDomain)) { return currDomain this.getRequestPath(); }即只要currDomain配置非空getUrl()就返回currDomain getRequestPath()其中getRequestPath()取自request.getRequestURI()并去除应用上下文前缀见 SaRequestForServlet.java。因此使用本方案时有两点需要注意curr-domain必须包含协议、域名、端口和上下文路径若外网访问存在额外路径前缀例如http://local.dev33.cn:8902/api由于返回结果是currDomain requestPathrequestPath来自 Servlet 容器的 URI 解析若反向代理同时改变了 URI 本身而非仅改变 host仍需结合 Nginx 配置保证requestURI的路径部分与外部访问路径一致。4.3 与方案一的取舍对比维度方案一header 策略重写方案二curr-domain 配置适用场景外网地址不固定、多域名/多环境动态切换外网访问地址固定不变配置复杂度需要同时改 Nginx 与 Java 代码仅需一行 yml 配置动态性每次请求从 header 实时取地址天然适配多域名静态地址域名变更需改配置安全要求必须保证 Nginx 统一注入 header防止前端伪造无额外安全注意点侵入性重写全局SaRequest创建策略影响面较大零代码侵入仅配置文件实际项目中若仅需在 SSO 场景下固定外网地址优先选择方案二若存在多套域名或复杂网关环境可选择方案一并务必遵守其两步同步的安全约束。五、补充getUrl()的正确使用姿势最后补充两个与本文主题相关的使用细节getUrl()不带 query 参数接口注释明确说明返回的是形如http://xxx.com/test的地址不含?xxxyyy。如果业务上需要完整 URI可在重写策略时自行拼接request.getQueryString()。Mock 环境同样可用在单元测试场景下SaRequestForMock.java 提供了可手动赋值的url字段测试时可以直接注入期望地址便于验证 SSO 等依赖getUrl()的流程。结语反向代理导致 URI 丢失是 Web 部署中的高频问题理解SaHolder.getRequest().getUrl()基于request.getRequestURL()的默认实现后就能明白其失效根因。Sa-Token 给出的两种官方方案——Nginx 透传 header 并重写SaStrategy.instance.setCreateSaRequest策略、或直接配置sa-token.curr-domain——分别覆盖了动态多域名与固定地址两类场景开发者可按需选用即可让 SSO 单点登录等依赖真实访问地址的模块在网关/代理环境下稳定工作。【免费下载链接】Sa-Token✨ 开源、免费、一站式 Java 权限认证框架让鉴权变得简单、优雅—— 登录认证、权限认证、分布式 Session 会话、微服务网关鉴权、SSO 单点登录、OAuth2.0 统一认证、jwt 集成、API Key 秘钥授权、API 参数签名项目地址: https://gitcode.com/GitHub_Trending/sa/Sa-Token创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/9/14 0:13:24

Keil MDK中文帮助文档离线配置全指南

简介:本资源为Keil MDK嵌入式开发环境的官方中文帮助文档合集,面向51/ARM架构初学者、嵌入式工程师及高校教学实践者,解决开发环境配置、项目构建、编译链接、调试排错等核心实操难题。压缩包共34个文件,主体为29个CHM格式离线帮助…

2026/9/14 0:13:24

Git协作实战:分支管理、PR流程与冲突解决全解析

Git 这东西,属于“单干时觉得没必要、一协作就原形毕露”的工具。你一个人 commit、push,永远碰不到分支管理和冲突解决;但只要你跟别人一起开发一个项目,哪怕只是两个人改同一个仓库,用不了多久你就会发现&#xff1a…

2026/9/14 1:13:29

**Nexus AI**, Co-Founder CTO

Nexus AI, Co-Founder & CTO 【免费下载链接】rendercv Resume builder for academics and engineers 项目地址: https://gitcode.com/GitHub_Trending/re/rendercv San Francisco, CA Jun 2023 – present Built foundation model infrastructure serving 2M mont…

2026/9/14 1:13:29

铝型材表面瑕疵识别:从数据标注到模型部署的工程实践

简介:基于深度学习的铝型材表面瑕疵识别项目,面向制造业质检人员、人工智能开发者和高校学生,聚焦利用机器学习与深度学习算法对铝型材表面缺陷进行自动检测与分类。压缩包共6个文件,整体仅234KB,包含5个Python脚本和1…

2026/9/14 1:13:29

sinc插值原理与MATLAB工程实现:带宽受限信号无失真重建

简介:本资源是一份面向信号处理与数字图像处理初学者及进阶学习者的 sinc 插值实践工具包,聚焦于高精度连续信号重建这一核心问题,适用于通信、音频重采样、医学图像插值等对保真度要求较高的工程场景。压缩包共含 2 个文件(1 个 …

2026/9/14 0:58:29

WorkBuddy连接实战:四层模型、Skill配置与业务系统集成指南

《WorkBuddy 实战蓝皮书》系列写到第三篇,前两篇聊了基础认知和本地环境搭建,后台收到不少私信,问得最多的问题集中在——装好之后怎么让它真正“通”起来?这个“通”不只是网络通畅,更是 WorkBuddy 跟你的电脑、你的资…

2026/9/13 0:01:16

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/14 0:03:22

KCF目标跟踪算法与OTB工程实现:毕业设计实战解析

简介:这是一份基于KCF核相关滤波算法、融合尺度池与抗遮挡处理的目标检测跟踪MATLAB完整源码,主要面向计算机相关专业准备毕业设计、课程设计或期末大作业的学生,也适合需要项目实战练习的初学者。源码在OTB数据集上完成验证,能够…

2026/9/14 0:03:22

语音情感识别实战:Keras实现LSTM、CNN、SVM与MLP多模型对比

简介:面向语音情感识别入门与进阶开发者,这份基于Keras的项目源码完整实现了LSTM、CNN、SVM、MLP四种模型,兼容Python3.8与Keras/TensorFlow2环境。压缩包内含49个文件,大小约70.31MB,主体包括Python脚本、yaml/json配…

2026/9/12 6:29:36

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/12 14:32:17

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/13 11:18:28

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码