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}

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

相关推荐
子兮曰2 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰2 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万2 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝2 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋2 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁2 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
汉堡大王95272 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大2 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师2 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端
沙蒿同学2 天前
我用 Go 搭了一条 AI Agent 流水线:从 1 张商品图到一整套淘宝详情页
前端·javascript·后端