我如何在零后端的情况下构建过期链接(仅使用 React + TypeScript)

发布: (2026年4月29日 GMT+8 10:12)
5 分钟阅读
原文: Dev.to

Source: Dev.to

介绍

大多数“过期链接”工具的工作方式相同:生成链接、在数据库中存储目标地址和过期时间、在每次点击时查询数据库,然后相应地重定向或阻止。
这种方式需要后端、数据库、服务器费用以及潜在的安全风险。

我的限制是:仅使用 React + TypeScript,部署在 Vercel 上,没有 Node.js、没有数据库、根本没有后端
解决方案是把链接数据直接编码进 URL 本身。

工作原理

当用户创建一个过期链接时,应用会:

  1. 获取目标 URL。
  2. 获取过期时间戳(Unix 毫秒)。
  3. 将它们组合成一个 JSON 对象。
  4. 使用 btoa()(Base64)对 JSON 进行编码。
  5. 将编码后的负载作为 URL 参数附加。
  6. 通过 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 博客

0 浏览
Back to Blog

相关文章

阅读更多 »