AIStacker
Web最佳实践指南8 分钟阅读

redirect_uri 与查询参数中的 encodeURI 和 encodeURIComponent

通过真实场景解释何时应编码完整 URL,何时应只编码单个参数或嵌套值。

本指南包含
3
本指南使用的工具
3
相关主题
6
指南概览

很多 URL 编码问题并不是因为选错了函数,而是因为在错误的边界上使用了正确的函数。开发者看到重定向失败后,往往直接在 encodeURIencodeURIComponent 之间二选一,结果只修好了一个测试场景,却在另一个场景里引入了新的问题。

真正应该先回答的问题不是“哪个函数更好”,而是“我现在编码的到底是什么”。它是浏览器最终要读取的完整 URL,还是要放进另一个 URL 里的单个值?这个边界一旦明确,编码方式的选择就会清晰很多。

01

把完整 URL 和嵌套值视为两种不同的边界

#

如果你眼前的字符串本身就是浏览器最终要访问的 URL,那么 encodeURI 风格通常更合理,因为它会保留 /?&= 这些顶层分隔符的可读性。

但如果这个字符串即将作为一个值被放进另一个 URL 里,情况就变了。嵌套的 redirect_uri 通常应该先作为单个 component 编码,否则它自己的 ?&= 很可能在外层 query string 中提前泄漏出来。

Note

线上最常见的错误,就是把嵌套 URL 当成已经处于顶层的最终 URL 来处理。

当你不确定边界时,用 URL Encoder 对比两种结果,通常比盲目试错更可靠。

本节相关工具

02

必须整体保留的值,应按单个 component 编码

#

如果一个 query value 里包含空格、&=,甚至另一个 URL,那么在拼到外层 URL 之前,通常应该先把它作为单个 component 编码。否则外层 parser 会过早拆分,把值的一部分误当成新的参数。

Read Only
Wrong:
/login?redirect_uri=https://app.example.com/callback?from=pricing&utm=ads

Safer:
/login?redirect_uri=https%3A%2F%2Fapp.example.com%2Fcallback%3Ffrom%3Dpricing%26utm%3Dads

第二种写法虽然不够直观,但更安全,因为嵌套目标会被保留为一个完整单元。在这种边界下,encodeURIComponent 风格通常更合适。

03

在再次编码之前,先确认是否已经过度编码

#

当输入里已经出现 %3A%2F 或大量 %25 这样的序列时,再做一次编码往往不是修复,而是在掩盖真正的问题。许多重定向 bug 的根源,就是同一个值在不同层被重复编码。

更稳妥的流程是:

  • 先观察当前输入原样
  • 判断它是完整 URL 还是单个 component
  • 只在那个边界上编码一次
  • 调试时如有需要,再解码一次查看内部结构

如果你无法清楚说明编码责任属于哪个层,那就说明现在还不应该继续补一层编码。

本节相关工具