Base64、URL 编码、HTML 实体这三样经常被混着叫「编码」,但它们解决的是完全不同的问题。用错的典型症状是:链接里的中文变乱码、参数里的加号消失、页面上显示出一串 <div>。
先记住一句话:这三种都不是加密,都能被任何人一键还原。
一、Base64:让二进制能走文本通道
Base64 把任意字节流用 64 个安全字符(A–Z、a–z、0–9、+、/)表示,末尾用 = 补齐。它的用途是让二进制数据能安全地通过只允许文本的通道,比如:
- 邮件附件(MIME 的历史需求);
- HTML 里内嵌小图标
data:image/png;base64,...; - JSON 字段里塞一小段二进制;
- JWT 的三段结构就是 Base64URL 编码的。
**代价是体积增加约 33%**。每 3 个字节变成 4 个字符,所以只适合小文件。把几 MB 的图片转成 Base64 内嵌进 CSS,会让首屏体积暴涨且无法单独缓存,通常是错误的优化。
Base64URL 变体:标准 Base64 里的 + 和 / 在 URL 中有特殊含义,所以 URL 场景用 - 和 _ 替代,并去掉末尾的 =。JWT、OAuth 里看到的就是这种。解码时如果报错,先检查是不是把两种变体搞混了,可以在 Base64 编码工具里切换处理。
中文怎么办:Base64 处理的是字节,不是字符。中文必须先按 UTF-8 转成字节再编码,否则不同环境结果不一致。这也是「同一段中文在两个系统 Base64 出来不一样」的原因——一边按 UTF-8,一边按 GBK。
二、URL 编码:让特殊字符能进地址栏
URL 里有一批字符是有语法含义的:? & = # / : + 空格。要把它们当普通数据传输,就得转义成 %XX 形式(百分号加十六进制字节值)。中文按 UTF-8 编码后每个汉字变成 3 个 %XX,所以 %E4%B8%AD 就是「中」。
encodeURI 还是 encodeURIComponent,这是最常问的:
encodeURIComponent编码更彻底,会转义? & = # /。用来编码单个参数值。encodeURI保留 URL 结构字符,不转义? & = # /。用来编码整条完整 URL。
判断方法:你手上的字符串是「一个值」还是「一条链接」。给参数值用前者,是最常见的需求。如果用 encodeURI 编码参数值,值里的 & 不会被转义,后端会把它当成参数分隔符,参数就被截断了——这也是一类真实的注入风险。
加号那个坑。表单默认的 application/x-www-form-urlencoded 格式把空格编码成 +,而 URL 路径里的 + 是字面加号。于是:
提交 "a+b",如果被当作表单编码解析,后端收到 "a b"
提交 "a b",如果被当作路径解析,收到的 %20 才是空格
密码、签名、Base64 字符串里带 + 时特别容易翻车。稳妥做法是把 + 显式编码成 %2B。
别重复编码。已经编码过的字符串再编码一次,% 会变成 %25,于是出现 %2520。前后端各编码一次是常见事故,特征是链接里出现 %25。
三、HTML 实体:让内容不被当成标签
把 < 变成 <、> 变成 >、& 变成 &、" 变成 ",作用是让这些字符在页面上显示为字符本身,而不是被浏览器当作标签或属性边界解析。
这件事的重要性在于安全:把用户输入的内容不做转义直接拼进 HTML,对方写一段 <script> 就能在别人浏览器里执行,这就是 XSS。
工程上的正确做法不是「手动调 HTML 实体编解码工具」,而是:
- 用框架的文本绑定(Vue 的
{{ }}、React 的{}),它们默认转义; - 避开
v-html、innerHTML、dangerouslySetInnerHTML,非用不可时先做白名单清洗; - 注意上下文不同转义规则也不同:放进属性、放进
<script>、放进 URL 参数各有各的转义方式,光转义<>不够。
手动工具的价值在排查:页面上显示出了 <div> 说明被转义了两次,看到标签被真的渲染了说明该转义的地方漏了。
四、Unicode 转义:\u4e2d 是怎么来的
\uXXXX 是把字符写成码点的十六进制形式,常见于 JSON 输出、Java properties 文件、代码里避免非 ASCII 字符。用 Unicode 编解码可以双向转换。
要注意的是代理对:超出基本平面的字符(emoji、部分生僻字)码点大于 U+FFFF,在 UTF-16 里用两个 \uXXXX 表示。所以按「4 个十六进制一组」硬拆会拆坏 emoji,字符串长度统计也会出现「一个 emoji 算两个字符」的现象。
五、编码不是加密
三者都是可逆的公开变换,任何人都能还原。这意味着:
- Base64 后的密码等于明文密码,只是不便直接肉眼读;
- 前端把参数 Base64 一下不构成任何安全措施;
- URL 里的敏感信息即使编码过,也会被浏览器历史、服务器日志、代理完整记录。
真正需要保密的内容要用加密(有密钥、不可逆推),本站的文本口令加密解密走的是 AES-GCM 加口令派生密钥,这才是「别人拿到密文也读不出内容」。
常见问题
Base64 解码报错怎么办?
先看长度是不是 4 的倍数(缺 = 补齐)、是不是混了 Base64URL 的 - _、有没有在复制过程中被插入换行或空格。
为什么后端收到的中文是乱码?
两边编码不一致。确认整条链路统一 UTF-8:页面 charset、请求头 Content-Type 里的 charset、后端解码方式、数据库字符集。任一环节是 GBK 就会乱。
URL 长度有限制吗? 标准没规定,但浏览器和服务器有实际上限(常见 2KB 到 8KB)。中文经 URL 编码后膨胀 3 倍,用 GET 传长文本很容易超限,应该改用 POST。
Base64 能压缩数据吗? 恰好相反,会变大约三分之一。需要减小体积应该先压缩(gzip、zip)再按需 Base64。
这些转换会上传内容吗? 不会。编解码全部在浏览器本地完成,token、密钥、业务数据不会离开你的设备。