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}

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

相关推荐
前端大卫3 分钟前
Vue3 + Element-Plus 自定义虚拟表格滚动实现方案【附源码】
前端
却尘18 分钟前
Next.js 请求最佳实践 - vercel 2026一月发布指南
前端·react.js·next.js
ccnocare19 分钟前
浅浅看一下设计模式
前端
Lee川23 分钟前
🎬 从标签到屏幕:揭秘现代网页构建与适配之道
前端·面试
Ticnix1 小时前
ECharts初始化、销毁、resize 适配组件封装(含完整封装代码)
前端·echarts
纯爱掌门人1 小时前
终焉轮回里,藏着 AI 与人类的答案
前端·人工智能·aigc
twl1 小时前
OpenClaw 深度技术解析
前端
崔庆才丨静觅1 小时前
比官方便宜一半以上!Grok API 申请及使用
前端
星光不问赶路人1 小时前
vue3使用jsx语法详解
前端·vue.js
天蓝色的鱼鱼1 小时前
shadcn/ui,给你一个真正可控的UI组件库
前端