首页/安全/加密与证书速查/URL 编码(百分号编码)
加密算法基础95 条

URL 编码(百分号编码)

RFC 3986 定义的百分号编码:把保留字符与非 ASCII 字符转为 %XX 形式;参数拼接与签名串构造中高频踩坑来源之一。

加密与证书速查安全更新于 2026-10-13

URL 编码是什么

URL 编码(百分号编码,percent-encoding)由 RFC 3986 定义:把 URL 中的保留字符、不安全字符与非 ASCII 字符转换为 %XX 形式的十六进制字节。中文字符需要先按 UTF-8 编码,再逐字节转义,所以一个汉字通常变成三段 %XX。查询参数拼接、接口签名串构造、重定向地址传递都依赖这套规则,它也是接口验签失败与参数错乱的高频原因。

基本信息

标准RFC 3986(URI 通用语法)
空格的两种写法路径中通常写 %20,表单查询串中可用 +
非 ASCII先按 UTF-8 编码,再逐字节转义
保留字符: / ? # [ ] @ ! $ & ' ( ) * + , ; = 是否转义取决于所处位置
大小写%XX 中的十六进制字母大小写等价,但签名需按对端约定统一

典型使用场景

  • 拼接带中文或含 & 与 = 的查询参数,否则参数会被截断或错位
  • 构造 API 签名串:排序、拼接、编码的顺序必须与文档一致
  • 生成带返回地址的跳转链接,returnUrl 需要整体编码后再作为参数传递
  • 处理表单提交,application/x-www-form-urlencoded 把空格编码为 +
  • 排查日志里 404 的路径:多半是编码缺失、路径段未转义或双重编码

编码与解码示例

编码与解码示例
import urllib.parse
print(urllib.parse.quote('中文 值'))         # %E4%B8%AD%E6%96%87%20%E5%80%BC
print(urllib.parse.quote_plus('a b&c'))    # a+b%26c(空格转 +)
print(urllib.parse.urlencode({'q': '中文'}))   # q=%E4%B8%AD%E6%96%87
print(urllib.parse.unquote('%E4%B8%AD'))   # 中(解码还原)
# quote 默认不转义 / ,处理路径段时要显式传 safe=''
# 命令行快速验证:curl -G --data-urlencode 'q=中文' https://example.com/search

编码不一致的症状

症状常见原因处理方式
参数值被截断值里的 & 未编码对每个值单独编码后再拼接
结果出现 %2520入参已被编码,代码又编码一次在出口统一做一次编码
验签失败编码顺序或字符集与文档不符按排序→拼接→编码→签名执行
中文乱码未按 UTF-8 编码后转义全链路统一 UTF-8
签名类接口的要求是「参数排序 → 拼接 → 统一编码 → 计算签名」,顺序错一步就会验签失败,而且报错往往只说签名不匹配。调试时把编码后的原始串打印出来,与文档逐字符比对,比反复猜测参数更快。

易错点

  • 只编码参数值不编码参数名(或反之)→ 含特殊字符时两端行为不一致,服务端解析出错
  • 双重编码产生 %2520 → 服务端解出的值多一层转义,业务校验与入库内容都错
  • 网关对 + 与 %20 的处理不一致 → 跨系统交互统一用 %20 更稳妥
  • 把编码当加密使用 → 百分号编码完全可逆,敏感信息不能靠它保护

数据来源与参考

  • RFC 3986(URI 通用语法)
  • WHATWG URL Standard(查询串约定)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌