返回 2026-05-24
🔒 安全

不要自行实现...Don't Roll Your Own ...

susam.net·2026-05-23

文章以密码学界的“不要自行实现加密算法”(Don't Roll Your Own Crypto)原则为引子,批判现代网页设计中的类似误区。作者指出,许多开发者忽视现成解决方案(如标准化UI组件库),反而重复造轮子,导致维护成本高、安全性差。类比密码学领域,强调复用成熟方案的重要性,尤其涉及用户隐私或系统安全时。

苏萨姆·帕尔于2026年5月23日

这篇文章将吐槽现代网页设计实践。但在进入正题前,我想先从一个密码学领域的熟悉原则说起。在软件开发者中,尤其是那些负责安全敏感系统的开发者之间,有一条广为流传的准则:不要自行实现加密算法。这并不意味着禁止任何人编写加密代码——总得有人去做。其核心含义是:对于保护用户敏感数据的普通生产软件,我们不应依赖未经广泛审查、未经验证的私有实现。应尽可能使用经过同行评审、久经考验的软件包或工具。

庆幸的是,如今行业已普遍避免自行实现加密算法,转而采用经过同行验证且经受时间考验的加密算法和工具包。二十年前可不是这样。职业生涯早期我曾见过多个存在缺陷的RC4自研实现,比如初始化向量不当、密钥流可预测以及明文部分泄漏到密文等问题,这些都可能危及用户敏感数据。但今天,主流电商网站或银行通常不会为Web服务使用自研加密方案。事实上,在支付、医疗和个人数据处理等受监管领域,这种做法可能违反强加密要求,甚至招致巨额罚款。

网页设计显然与密码学无关。滚动条故障和加密方案失效并非同类问题。但我希望网页设计领域也能有一条类似的准则。我认为,当X是浏览器早已擅长且用户每天依赖的功能时,开发者就不该自行实现X。以下是我列出的这类X。

  • 不要自行实现页面滚动功能。
  • 不要自行实现链接导航。
  • 不要自行实现文本选择。
  • 不要自行实现右键菜单。
  • 不要自行实现复制粘贴。
  • 不要自行实现密码输入框。
  • 不要自行实现日期选择器。
  • 当然,某些场景下确实需要自行实现X。但本文重点讨论不该自行实现X的情况,以及这样做如何导致用户体验变差(至少基于我的观察)。我并非主张永远不自己动手——作为经常进行创意计算并偶尔开发有趣工具的人,我非常支持自主开发。但对于人们必须使用的严肃网站UI功能,我希望软件开发社区能更审慎地决定哪些炫酷功能值得加入,哪些应该舍弃。请记住,我对用户体验并非专家,远谈不上。因此本文所有观点都不应被视为建议。我只是作为普通用户发现某些现代网页模式令人沮丧。此文仅代表一名用户的抱怨,而非设计指南。

    在所有我提到的这些问题中,最让我困扰的是网页上的自定义滚动行为。我已经习惯了页面滚动对鼠标、触控板或键盘输入的响应方式。当你用自定义实现覆盖浏览器的默认滚动行为时,页面对我来说就“卡住了”。现在滚动时要么太慢要么太快,键盘滚动可能完全失效。你原本让我毫不费力就能完成的操作,变成了需要刻意注意的新问题。

    另一个让我抓狂的是自定义链接导航。浏览器本已能完美处理超链接——这甚至就是浏览器存在的根本意义。链接跳转是它们的核心功能,不该被随意干扰。若你认为必须修改这种行为,请先重新审视目标是否真的值得破坏常规链接体验。GitHub 在这方面堪称反面典型:点击文件链接或 issue 链接时,它会触发一套复杂的 JavaScript 接管跳转逻辑。不信的话,用 Firefox 或 Chrome 打开任意 GitHub 项目,按 F12 调出开发者工具,在“调试器”或“源代码”标签页中找到右侧边栏的“事件监听断点”,展开“鼠标”并勾选“点击”,再点击 GitHub 上的链接,观察实际效果。

    想必不止我一个人发现过:GitHub 上有时点击链接加载耗时过长,反而在新标签页打开反而更快。这种矛盾现象恰恰源于其 JavaScript 在当前标签页处理导航时的性能瓶颈。

    自定义密码输入框同样是隐患。所幸这类情况近年已减少,浏览器原生密码输入框功能完备:可保存密码、自动填充、生成高强度密码,还能在 HTTP 不安全连接提交时发出警告,与密码管理器、辅助工具和移动键盘协同工作。若替换为自定义密码框,可能破坏所有这些功能;更常见的是改用普通文本字段自行隐藏内容,此时浏览器、操作系统或辅助工具会将其视为可见文本而非密码,导致密码意外暴露。

    自定义日期选择器是另一个常见的烦恼。我知道 `<input type="date">` 无法帮助你选择日期范围,但这也没关系。你可以提供两个日期输入框,一个用于开始日期,一个用于结束日期。如果这意味着我可以用最喜欢的网页浏览器以相同的方式浏览日历并选择日期,我愿意为使用两个不同的输入框来选择日期范围付出小小的代价。我不愿意去学习十个不同网站中十种不同实现的日期选择器的十种不同用法。目前,日期选择器的实现方式五花八门。有些要求你缩小月份视图才能进入年份视图以便选择年份,而一旦进入年份视图就无法再切换回月份视图;有些要求你连续点击“上一年”按钮四十次才能选择出生年份(如果你足够老的话);还有些根本不允许手动输入日期。不,我不想学习你们的日历小部件。我只想在最喜欢的浏览器中使用日期选择器——这已经很合理了,比你们的自定义实现更可靠。如果你们需要日历小部件来支持原生日期选择器功能不足的旧浏览器,或许应该将其作为原生选择的补充而非替代。例如,普通的 `<input type="date">` 元素可以保持原样,同时额外提供一个自定义小部件,让用户操作同一个字段即可。

    总之,别再折腾表单控件了。它们几乎总是为了解决现有问题而引入新问题。顺便说一句,也别再每隔几个月就改一次网站的布局和界面!我可以适应新设计,但我的年迈亲戚们不行。对他们而言,每次改动用户界面都等于要重新学习一套全新工具。如果所有网站都每隔几个月就如此折腾,用户不得不花费大量时间重新熟悉本应熟悉的功能,却毫无实际收益。请让他们安享晚年就好。想象一下,如果某个 Linux 发行版每隔几个月就重写所有核心命令及其命令行选项,你会作何感想?或者想象一下,如果洗衣机上的按键每天早晨都被重新排列,那会是什么体验?肯定不会愉快!

    需要完整排版与评论请前往来源站点阅读。