我如何在零后端的情况下构建过期链接(仅使用 React + TypeScript)
Source: Dev.to
介绍
大多数“过期链接”工具的工作方式相同:生成链接、在数据库中存储目标地址和过期时间、在每次点击时查询数据库,然后相应地重定向或阻止。
这种方式需要后端、数据库、服务器费用以及潜在的安全风险。
我的限制是:仅使用 React + TypeScript,部署在 Vercel 上,没有 Node.js、没有数据库、根本没有后端。
解决方案是把链接数据直接编码进 URL 本身。
工作原理
当用户创建一个过期链接时,应用会:
- 获取目标 URL。
- 获取过期时间戳(Unix 毫秒)。
- 将它们组合成一个 JSON 对象。
- 使用
btoa()(Base64)对 JSON 进行编码。 - 将编码后的负载作为 URL 参数附加。
- 通过 TinyURL 的 API 对完整 URL 进行缩短。
// Create payload
const payload = {
url: destinationUrl,
exp: expiryTimestamp
};
const encoded = btoa(JSON.stringify(payload));
const longUrl = `https://onetimelink.vercel.app/r?d=${encoded}`;
// Shorten (TinyURL)
const shortUrl = await shortenWithTinyURL(longUrl);
当有人访问短链接时,TinyURL 会把它展开回长 URL。React 应用随后在客户端解码该参数:
const params = new URLSearchParams(window.location.search);
const encoded = params.get('d');
if (!encoded) {
// Invalid link
return;
}
try {
const payload = JSON.parse(atob(encoded));
const now = Date.now();
if (now > payload.exp) {
// Expired — show expiration screen
setExpired(true);
} else {
// Valid — redirect
window.location.href = payload.url;
}
} catch {
// Malformed link
setInvalid(true);
}
没有数据库查询,没有服务器调用,也没有任何地方存储数据。链接自身携带过期信息,是否重定向或阻止的决定全部在浏览器中完成。
好处
- 零存储 → 零泄露面。 数据仅存在于共享的 URL 中。
- 无服务器费用。 产品运行在 Vercel 免费层;访问链接时不涉及服务器端计算。
- 可离线使用(部分)。 如果 URL 被缓存,过期检查仍然有效,因为它只是时间戳比较。
限制
| 限制 | 细节 |
|---|---|
| URL 长度 | 对 JSON 对象进行 Base64 编码会增加字符数。TinyURL 能缩短链接,但中间的长 URL 仍可能很长。 |
| 无服务器端验证 | 用户可以解码负载、修改过期时间戳、重新编码,从而生成“永不过期”的链接。适用于普通使用场景,不适合对抗性环境。 |
| 无分析功能 | 没有服务器端存储,就无法统计点击次数或查看仪表盘。 |
| 无法提前撤销 | 链接创建后只能等时间戳到期,无法提前删除。 |
理想使用场景
- 临时登录凭证 用于交接。
- 评审期间的预发布环境链接。
- 带自然结束日期的私密文档。
在这些场景下,限制是可以接受的:客户端点击一次,获取所需内容,窗口关闭后链接即失效。
如果需要分析、多次点击追踪或提前撤销,则必须使用正式的后端。
技术栈
- React + TypeScript
- Vite 用于打包
- Vercel(免费层)用于部署
- TinyURL API(免费层,无需认证)
- 浏览器内置函数
btoa()/atob()用于编码
整体服务器基础设施成本: $0。
结论
当你需要临时共享敏感链接且不想承担后端开销时,将过期数据编码进 URL 是一种可行的零成本方案。实时实现已上线——免费使用,无需账户。
更多关于架构和产品方向的细节,请参阅 OneTimeLink 博客。