URL重定向需要多次encodeURIComponent

前言

最近在对接公司SSO(单点登录)的登出功能时,我遇到了一个让人抓狂的问题:

需求很简单 - 用户点击登出后,需要经过三次URL跳转,最终重定向到第三方系统。
实现也很"简单" - 我直接把所有参数拼接成一个大长URL。
结果却很"魔幻" - 要么跳转后参数神秘消失,要么直接404,最离谱的是有时候竟然跳转到了完全错误的地址!

经过和这个问题大战三百回合后,我终于明白:URL跳转就像俄罗斯套娃,每一层都需要精心包装(编码),否则就会"散架"

分析 & 解决

下面我就用"破案式"的步骤,带大家完整复盘这个问题的:

1️⃣ 第一现场还原 - 直观感受问题现象

  1. 先跳SSO登出接口 https://sso.corp.com/logout
  2. 再跳认证中心 https://auth.corp.com/redirect
  3. 最后到监控系统 https://monitor.example.com/home
js 复制代码
const finalUrl = `https://sso.corp.com/logout?redirect=https://auth.corp.com/redirect?target=https://monitor.example.com/home`

诡异现象

  • 有时跳到https://auth.corp.com/redirect?target=https就停了
  • 有时监控系统收到的是乱码参数
  • 最严重时直接跳到了https://example.com(危险!)

💡 关键发现 :浏览器控制台看到实际请求的URL中?=都消失了!

2️⃣ 线索收集 - 对比编码前后的URL差异

未编码的URL

text 复制代码
https://sso.corp.com/logout?redirect=https://auth.corp.com/redirect?target=https://monitor.example.com/home

正确编码后

text 复制代码
https://sso.corp.com/logout?redirect=https%3A%2F%2Fauth.corp.com%2Fredirect%3Ftarget%3Dhttps%3A%2F%2Fmonitor.example.com%2Fhome

关键区别

字符 未编码 编码后
: : %3A
/ / %2F
? ? %3F
= = %3D

🔍 实验证明:用Postman测试发现,编码后的URL能100%正确跳转

3️⃣ 关键突破 - 为什么需要层层编码?

三层跳转的编码逻辑

具体原因

  1. 防止解析歧义

    当遇到redirect=https://auth.corp.com/redirect?target=xxx时:

    • 未编码:服务器会误认为target=是第一个参数
    • 编码后:整个URL变成单个参数值
  2. 安全防御

    假设攻击者构造:

    text 复制代码
    https://sso.corp.com/logout?redirect=http://hacker.com#https://auth.corp.com

    编码后会变成无害字符串:

    text 复制代码
    http%3A%2F%2Fhacker.com%23https%3A%2F%2Fauth.corp.com

4️⃣ 完美复现 - 手把手演示正确编码方式

正确实现代码

javascript 复制代码
// 第三层(最内层)
const monitorUrl = 'https://monitor.example.com/home';
const encodedMonitor = encodeURIComponent(monitorUrl); 

// 第二层
const authUrl = `https://auth.corp.com/redirect?target=${encodedMonitor}`;
const encodedAuth = encodeURIComponent(authUrl);

// 第一层(最外层)
const finalUrl = `https://sso.corp.com/logout?redirect=${encodedAuth}`;

逐层编码结果

  1. 原始第三层:
    https://monitor.example.com/home
  2. 编码后第三层:
    https%3A%2F%2Fmonitor.example.com%2Fhome
  3. 拼接第二层:
    https://auth.corp.com/redirect?target=https%3A%2F%2Fmonitor.example.com%2Fhome
  4. 编码第二层:
    https%3A%2F%2Fauth.corp.com%2Fredirect%3Ftarget%3Dhttps%253A%252F%252Fmonitor.example.com%252Fhome
    (注意:这里的%25%的编码)

5️⃣ 防范手册 - 总结编码规范和安全要点

黄金法则

✅ 所有动态生成的URL参数必须编码

✅ 嵌套多少层就编码多少次

✅ 永远使用encodeURIComponent而不是encodeURI

安全检查清单

  1. 确认每个?=都被编码
  2. 测试包含#&等特殊字符的情况
  3. 验证最终URL长度不超过浏览器限制(约2000字符)
  4. 对输入域名做白名单校验

应急锦囊

当遇到跳转异常时,可以:

  1. console.log打印每一层编码结果
  2. 使用在线URL解码工具逆向检查
  3. 在Network面板查看实际请求URL

附录:编码速查表

场景 正确写法 错误写法
普通参数 ?name=${encodeURIComponent('测试')} ?name=测试
嵌套URL ?redirect=${encodeURIComponent(url1)} ?redirect=${url1}
多参数 ?x=${encodeURIComponent(a)}&y=${encodeURIComponent(b)} ?x=${a}&y=${b}

再也不用担心编码问题啦! ✨

相关推荐
kirk_wang3 小时前
Flutter 导航锁踩坑实录:从断言失败到类型转换异常
前端·javascript·flutter
静小谢4 小时前
前后台一起部署,vite配置笔记base\build
前端·javascript·笔记
用户47949283569155 小时前
改了CSS刷新没反应-你可能不懂HTTP缓存
前端·javascript·面试
还好还好不是吗5 小时前
老项目改造 vue-cli 2.6 升级 rsbuild 提升开发效率300% upupup!!!
前端·性能优化
sumAll5 小时前
别再手动对齐矩形了!这个开源神器让 AI 帮你画架构图 (Next-AI-Draw-IO 体验)
前端·人工智能·next.js
OpenTiny社区5 小时前
2025OpenTiny星光ShowTime!年度贡献者征集启动!
前端·vue.js·低代码
wangan0945 小时前
不带圆圈的二叉树
java·前端·javascript
狗哥哥5 小时前
从零到一:打造企业级 Vue 3 高性能表格组件的设计哲学与实践
前端·vue.js·架构
疯狂平头哥5 小时前
微信小程序真机预览-数字不等宽如何解决
前端
Drift_Dream5 小时前
前端趣味交互:如何精准判断鼠标从哪个方向进入元素?
前端