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}

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

相关推荐
tianzhiyi1989sq24 分钟前
Vue3 Composition API
前端·javascript·vue.js
今禾30 分钟前
Zustand状态管理(上):现代React应用的轻量级状态解决方案
前端·react.js·前端框架
用户25191624271132 分钟前
Canvas之图形变换
前端·javascript·canvas
今禾39 分钟前
Zustand状态管理(下):从基础到高级应用
前端·react.js·前端框架
gnip1 小时前
js模拟重载
前端·javascript
Naturean1 小时前
Web前端开发基础知识之查漏补缺
前端
curdcv_po1 小时前
🔥 3D开发,自定义几何体 和 添加纹理
前端
单身汪v1 小时前
告别混乱:前端时间与时区实用指南
前端·javascript
鹏程十八少1 小时前
2. Android 深度剖析LeakCanary:从原理到实践的全方位指南
前端
我是ed1 小时前
# cocos2 场景跳转传参
前端