← 路由设计 · 稳定入口与可变目标 / 短链接 · 为什么会存在 · 把长地址压成人能用的代号 待审核 2 / 23

短链接 · 为什么会存在 · 把长地址压成人能用的代号

你随手复制的一条链接,常常是一两百个字符,后面拖着一长串给机器看的 utm_* / ref tracking 参数。它机器能用,人却几乎用不了——没法念给人手敲、塞不进有字数上限的短信、印成二维码后码点过密难以扫描、贴进聊天框还折成三行。

短链就是来解决这个「长度 / 可用性」问题的:把任意长的 URL 换成一个极短、固定长度的代号 vega.link/aB3xK,真正的长地址存在服务端一张表里,访问短码时再 301/302 跳过去——这正是「为什么要有路由这一层」讲的那层 indirection 最直接的实例。它同时附带获得了 indirection 的全部好处(改址 / 统计 / 灰度),但它首先解决的,是「长度」这个最朴素的问题。

短链的本质,就一句话:一张映射表codeURLcode \to 长 URL)+ 一次 301/302 跳转。短码极短(几个字符),所以它能念、能记、能印、能扫;真实目标藏在服务端,所以你随时能改它、能在跳转那一下记统计、能按渠道灰度——后面这一串好处和「为什么要有路由这一层」讲的完全是同一招,短链只是它最常见的实例。

1 · 为什么短码能这么短 · 自增 id 到 base62

短码怎么生成才能又短又不撞?最经典的做法:每来一个新链接,数据库给它一个自增 id(1, 2, 3…),再把这个十进制 id 用 base620-9 a-z A-Z 共 62 个字符)编码。base62 比十进制「进制大」,同样的数用更少的字符就能写完——而且自增天然不重复,不像随机短码要查重、也不像 hash 截断会撞。拖动下面的 id 看短码怎么变:

2 · 自增 id 的风险 · 别人能顺着猜到其他链接

base62 只是换了进制,是可逆的双射——拿到一条短码解回 id,id±1id \pm 1 就是相邻的另一条短链。于是只要从 1 一路加上去,就能把整库的目标 URL 全爬下来(enumeration / IDOR);即便短码本身不可逆,单调递增也会泄露规模与增速——看到 id 到了 5000 万就知道你发了多少、采样两次还能算增长,这是经典的「德国坦克问题」。真实事故:goo.gl / 早期 bit.ly 都被枚举过,暴露出大量本以为「不公开」的网盘分享。要害是一句话:短码的「难猜」当不了访问控制,它只负责寻址

上面右列用一个可逆置换把 id 打乱成同位宽的不可预测码——仅作示意。真实生产里这个置换必须是密码学强的(FPE 格式保留加密 / 一个小 Feistel 网络),否则像这里的线性置换,被采几个样本就能反推出规律。

3 · 补救 · 让短码既不撞、又不可枚举

三种主流方案,都在保住「短」的前提下消除「可猜」:

方案 怎么做 权衡
随机短码 不用 id,直接随机生成 6–8 位 base62(如 aB3xK)。 最简单;但要查重防撞(生成后查库,撞了重生成),或靠空间够大让撞概率可忽略。
加密自增 id 内部仍自增(不撞 / 好分库),对外只暴露 encrypt(id) 的结果。 兼顾两者。Sqids / Hashids 只能阻止随手枚举,不是加密(顺序可被还原);需要强保证时用 FPE / Feistel
自增 + 随机校验位 短码 = base62(id) 再拼几位随机后缀。 改动最小;但 id 段仍单调,规模 / 增速照样泄露,只挡住了「±1 猜邻居」。

能接受查库防撞就选随机方案,最简单;想保留自增的内部好处就用加密,需要强保证时用 FPE / Feistel,不要只依赖 Hashids。

最后一道底线:凡是真正私密的目标(私人相册、未发布草稿、内部文档),不要拿短码的「难猜」当门禁。短码再随机也只是 security through obscurity——链接一旦泄露就全开。访问控制(登录 / 权限 / 过期 / 一次性 token)必须另做一层,短码只管寻址。这正是分享入口页 open redirect 同一条原则的另一面:跳转这件事本身不可信任输入。

4 · 长 URL vs 短链 · 差在哪

维度 直接发原始长 URL 发短链
字数受限渠道(短信 / 微博) 占满甚至超限,拆多条 / 吃光字数 ✗ 十几字符,正文随便写 ✓
二维码 version 高、码点密,印小后难以识别 ✗ version 低、稀疏,易扫描 ✓
口播 / 印刷 念不出来、折行、字号极小 ✗ 一行大字、能逐字念 ✓
发出后改目标 已印 / 已发的改不了 ✗ 改服务端映射表,全部跟随 ✓
来源统计 utm 自带但落地页各算各的 ✗ 跳转那一下统一记录 ✓
代价 无(但前几行的债都留着) 多一跳 + 一张表 + 依赖短链服务存活

前三行(长度 / 可用性)是短链独有的存在理由;后两行(改址 / 统计)是它从 indirection 附带获得的好处,详见「为什么要有路由这一层」「分享地址统一入口」

短链的代价不容忽略:link rot。真实地址被藏在某一家短链服务背后——这家一旦关停(Google 的 goo.gl 已下线、不少免费服务转付费墙后清库),所有印在海报 / 名片 / 书里的短链随即全部变成死链,且无法挽救(你手里只有短码,原始 URL 在别人库里)。重要长期链接要么自建短链域名、要么直接用原始 URL。另外短链看不出真实目标,也常被钓鱼利用——这正呼应分享入口页的 open redirect:跳转目标必须可控、过 allowlist。

5 · 相关页