Have I Been Pwned 2.0 正式上线:全新网站架构、API与安全功能解析

Troy Hunt宣布Have I Been Pwned 2.0版本正式上线,涵盖全新网站架构、改进的搜索功能、API文档优化、域名搜索增强、仪表盘统一及反自动化措施,采用.NET 9.0、Azure服务和Cloudflare技术栈。

Have I Been Pwned 2.0 正式上线!

2025年5月20日

经过漫长的努力和马拉松式的开发,全新的Have I Been Pwned(HIBP)网站终于上线了!去年二月,我首次向公共代码库提交了 rebranded 服务的代码,今年三月我们软启动了新品牌。在这段时间里,我们完全重建了网站,改变了几乎所有网页的功能,添加了大量新功能,甚至今天还推出了一个商品商店😎。让我带您了解一些亮点,系好安全带!

搜索功能

HIBP的标志性功能是首页的大搜索框,现在它更好了——它有彩花!不过,不是每个人都能看到,只有大约一半的用户会看到庆祝响应。这种响应故意设计得欢快,原因如下:当我们与全球用户交流时,一个主题反复出现:HIBP有点 playful。它不是一个充满连帽衫、锁图标和恐吓“暗网”的可怕地方。相反,我们旨在让大众更容易接受,提供事实性、可操作的信息,没有夸张。彩花枪(是的,有好几个,而且是动画的)让气氛轻松一些。另一种情况是您会看到红色响应:

我们曾短暂考虑过在这个页面上采用更轻松的处理方式,但 somehow 一点悲伤的长号似乎不太合适,所以我们选择了更含蓄的响应。但现在,它在一个时间线上,您可以按时间倒序滚动,每个泄露事件都总结了发生了什么。如果您想要更多信息,我们有一个全新的页面,稍后我会谈到。

首先,一个小变化:我们从网站上移除了用户名和电话号码搜索支持。用户名搜索是在2014年Snapchat事件中引入的,电话号码搜索是在2021年Facebook事件中引入的。仅此而已。这是我们唯一一次加载这些类别的数据,有几个很好的理由。首先,与电子邮件地址相比,它们很难从泄露中解析出来(我们使用正则表达式提取电子邮件地址,并开源了代码)。用户名是一个字符串。电话号码,嗯,取决于情况。它们不仅仅是数字,因为如果您正确国际化它们(如Facebook事件中那样),它们前面还有一个加号,但格式经常五花八门。而且我们无法发送通知,因为没有人“拥有”一个用户名,而发送短信到电话号码比发送电子邮件昂贵得多。此外,除了这两个事件,HIBP中的其他所有事件都有电子邮件地址,所以如果我们问“have I been pwned?”,我们总是可以回答这个问题,而无需加载这两个难以解析的字段,这些字段在大多数泄露中通常不存在。当旧网站提供在搜索框中接受它们时,它造成了混乱和支持开销:“为什么我的号码不在[无论什么]泄露中?!”这就是为什么它从网站上消失了,但我们在API中保留了支持,以确保不破坏任何东西…只是不要期望在那里看到更多数据。

泄露页面

我们创建这个新页面的原因有很多,尤其是首页的搜索结果变得太忙了,我们想把细节放到别处。所以,现在每个泄露都有一个专用页面,例如:

这主要是我们已有的信息(尽管以更用户友好的方式显示),但新页面的独特之处在于提供了更针对性的建议,关于泄露后该做什么:

我最近写了关于这个部分,以及我们计划如何识别其他合作伙伴,为发现自己处于泄露中的人提供适当的服务。例如,身份保护提供商对许多数据泄露来说很有意义。

既然我们已经上线,我们还将努力用更多泄露和用户特定数据来充实这个页面。例如,如果服务支持2FA,那么我们会特别指出,而不是依赖上面的通用建议。密码钥匙也是如此,我们会添加一个部分。最近在英国与NCSC的讨论涉及添加本地化的数据泄露指导,例如,向英国用户显示NCSC徽标和链接到他们的资源(该资源推荐检查HIBP🙂)。

我相信我们还可以做更多,所以如果您有任何好主意,请在下面给我留言。

仪表盘

我们现在将所有不同的地方统一到一个中央仪表盘:

从左边的导航栏一眼看去,您可以看到很多熟悉的功能,这些功能几乎不言自明。这些结合了大众相关的内容和更面向业务的内容。它们现在都在一个“登录”后面,在显示前验证电子邮件地址的访问权限。将来,我们还将添加密码钥匙支持,以避免需要先发送电子邮件。

仪表盘方法不仅仅是把现有功能移动到一个旗帜下;它还将为我们提供一个平台,在未来构建需要先验证电子邮件地址的新功能。例如,我们经常被要求提供让人们能够将他们家庭的电子邮件地址订阅通知,但让通知发送到不同的地址。我们中的许多人为他人提供技术支持,这将是一个真正有用的功能,放在您已经验证电子邮件地址的地方是有意义的。所以,请期待这个功能,以及许多其他功能。

域名搜索功能

这个功能花费的时间比大多数其他功能加起来还多。我们在这里尝试了很多,从一个更清晰的已验证域名列表开始:

搜索结果现在提供了更清晰的摘要,并添加了按电子邮件地址和按最新泄露(这是下拉菜单中的热门新功能)的过滤:

所有这些搜索现在只从API返回JSON,整个仪表盘充当单页应用,所以一切都非常敏捷。上面的过滤是纯客户端针对域名搜索的完整JSON进行的,我们测试了这种方法,即使域名有超过25万个泄露电子邮件地址,仍然可行(尽管可以说,您真的希望通过API获取数据,而不是在浏览器窗口中滚动查看)。

域名所有权的验证也完全重写,有了更清晰、更简单的界面:

我们还有工作要做,以使非电子邮件验证方法更顺畅,但以前也是如此,所以至少我们没有退步。那很快就会发生, promise!

API

首先:API本身没有变化。这次更新不会破坏任何东西!

在UX重建GitHub仓库上有一个关于API文档正确方法的讨论。普遍共识是OpenAPI,我们开始使用Scalar走这条路。事实上,您甚至可以看到Stefan在这里haveibeenpwned.com/scalar所做的工作:

它非常酷,尤其是它以各种不同语言记录样本的方式,甚至有一个测试运行器,这实际上是浏览器中的Postman。很酷,但我们就是没时间完成它。因此,我们暂时保留了旧文档,只是进行了样式化,使其看起来像网站的其余部分(我认为仍然很 slick),但我们确实打算在不受如此大发布压力时滚动到Scalar实现。

商品商店

您知道还有什么很 awesome 吗?商品!不,严肃地说,多年来我们收到了很多对HIBP品牌商品的请求,现在,我们来了:

我们现在实际上有一个真实的商品商店在merch.haveibeenpwned.com!考虑到我们必须做多少机械工作来让所有新东西工作,这可能是我们时间的最糟糕使用,但这对Charlotte来说是一个 passion project,所以是的,现在您实际上可以购买HIBP商品。一切都是通过Teespring完成的(我在哪里听过这个名字?!),那里列出的所有东西都是成本价——我们绝对不赚钱,这只是为社区做的一个有趣的倡议🙂

我们也尝试了他们的贴纸选项,但它们远远不及我们在Sticker Mule上的小单件商店已有的东西,所以目前,那仍然是笔记本电脑装饰的首选。或者就去抓取开源艺术品,从您喜欢的任何地方打印您自己的。

技术细节

我们仍然在Microsoft Azure上运行原始服务,使用App Service用于网站,“无服务器”Functions用于大多数API(那里仍然有一些异步的,作为基于浏览器功能的一部分被调用),SQL Azure“Hyperscale”和存储账户功能,如队列、blob和表。几乎所有的编码都是C# with .NET 9.0和ASP.NET MVC on .NET Core用于Web应用。Cloudflare仍然扮演着重要角色,有很多代码在workers中,数据在R2存储中,以及所有围绕WAF和缓存的好东西。我们现在也独家使用他们的Turnstile服务进行反自动化,并完全抛弃了Google的reCAPTCHA—— big yay!

前端现在是最新一代的Bootstrap,我们使用SASS用于所有CSS,TypeScript用于所有JavaScript。我们在冰岛的(另一位)人Ingiber刚刚在界面上做了一份绝对出色的工作,大大超出了我们所有的期望。我们现在拥有的远远超出了我们开始这个过程时的预期,很大一部分是Ingiber的能力,能够把一个简单的要求变成一件美丽的东西😍我很高兴Charlotte、Stefan和我上个月在雷克雅未克与他共度时光,分享了一些啤酒。

我们还对网站性能进行了一些可衡量的改进。例如,我在取下旧网站之前运行了一个Pingdom网站速度测试:

然后在新网站上运行它:

所以我们削减了28%的页面大小和31%的请求。加载时间大致相同(而且变化很大),但对右侧列中的所有值有可靠的测量是一个非常令人满意的结果。还要考虑任何Web开发人员多年来会看到的关于网页变得多大的评论,而11年后我们在这里削减了坚实的两位数百分比!

最后,任何可能被解释为跟踪或广告膨胀的东西都不在那里,因为我们根本不做任何那种事情🙂事实上,我们唯一真正的流量统计数据是基于Cloudflare在流量流过他们的边缘节点时看到的情况。而那1Password产品展示,一如既往,只是文本和图像。我们甚至不跟踪外链点击,那是他们的事,如果他们想在登陆页面上捕获的话。这实际上使得与想要产品展示的身份盗窃公司的讨论更加困难,因为他们习惯于获得侵入性跟踪产生的数字,但我们不会以其他方式做。

AI

我想在这里快速提一下这个,因为AI似乎要么 constantly overblown,要么 denigrated。要么它将解决世界的问题,要么它只产生“slop”。我特别在这次重建中广泛使用了Chat GPT,尤其是在最后几天时间紧张、大脑 fried 的时候。以下是一些它产生重大影响的例子:

我使用Bootstrap图标从这里:https://icons.getbootstrap.com/

什么是一个好图标来说明一个叫做“Index”的标题?

这是在最后关头,当我们意识到我们没有时间正确实现Scalar时,我需要快速将所有现有的API文档迁移到新模板。那个页面上有超过2,000个图标,这种方法意味着每次找到正确的图标大约需要30秒。

我们在旧网站上删除了一些页面,但在滚动之前,我想确切知道那里有什么:

给我写一个PowerShell脚本来爬取haveibeenpwned.com并写出它找到的每个唯一URL

然后:

现在写一个脚本来获取它找到的所有路径,并查看它们是否存在于stage.haveibeenpwned.com上

它也找到了好东西,比如我忘记迁移的security.txt文件。它也找到了从未存在的东西,所以这是通常的“信任,但验证”情况。

还有无数的小事情,每次我需要从一些CSS建议到配置Cloudflare规则到.NET Core Web应用中的 idiosyncrasies,正确答案都在几秒钟内。我会说它90%的时间是正确的,如果您现在在软件开发工作中没有积极使用AI(而且我相信还有更好的方式),我 pretty confident 地说“you’re doing it wrong”。

旅程到这里

很难解释投入了多少,这远远超出了今天您在网站上看到的内容。似乎是小事,比如使用条款和隐私政策的微小修订,这需要许多小时的时间和数千美元的律师费用(只是对我们如何处理数据的微小更新和新服务如窃取器日志的反映)。我们在周日凌晨我的时间推出了新网站,几乎一切顺利:

一两个小故障,我们快速修复和推送,仅此而已。我实际上等到现在,上线两天后,才发布这篇文章,以便我们首先尽可能多地解决问题。从那时起,我们已经推送了十几个新版本,只是为了快速迭代和精炼。TBH,这有点 intense,并且是一个极其耗时的努力,主导了我们的注意力,尤其是在发布前的最后几周。只是为了强调这一点,我周一早上第一件事就收到了健康警报:

没有什么比经验数据更能说明问题了!那个我们上线的最后一个周末尤其 brutal;我认为几十年来我没有为软件发布投入那么多高强度时间。

Have I Been Pwned 现在是我生命的四分之一 passion。我在2013年建造的东西从未 intended 带我这么远或持续这么久,如果我诚实的话,我有点 shocked。我觉得我们用这个新网站和新品牌建造的东西将这个 little pet project 提升到了一个严肃的服务,具有新的专业水平。但我希望在阅读本文时,您看到它保持了服务一直伟大的所有东西,我很高兴今天仍然在这里写关于它的第205篇博客文章。感谢阅读,现在去享受新网站吧😊

编辑(最初发布几小时后):让我扩展一下Cloudflare的Turnstile,因为它会解释一些人看到的一些 idiosyncrasies:

这是一种反自动化方法,不涉及将流量交给Google(如reCAPTCHA所做),并且可以完全无形地实现。有更侵入性的实现,但我们在这里尝试无缝。它涉及一些Cloudflare脚本在浏览器中运行并提供挑战,然后与HTTP请求一起提交并在服务器端验证。自2023年以来,我们以某种形式在HIBP上拥有它,它可以很 awesome…直到它不是。如果挑战失败,接下来会发生什么?取决于情况。

在我们真的需要阻止机器人的表单上(例如,任何发送电子邮件的),失败的Turnstile挑战最初只是显示一个红色错误。现在它说:

我们的反自动化过程认为您是一个机器人,您显然不是!尝试表现得像一个人,再次点击按钮,如果它仍然行为不当,给页面重新加载。

我们经常发现第二次点击或页面重新加载解决了问题,所以希望这能引导人们走向正确的方向。如果没有,我们将需要研究更 in-your-face 的Turnstile实现,显示一个您需要与之交互的小部件。要自己尝试并查看它的行动,试试仪表盘登录页面。

Turnstile heavily 特征的另一个地方是在网站根目录的主搜索页面。我们不希望那个API被机器人击中,所以那里是 must have。在这里,像在新网站的其他页面上一样,我们异步发布到API端点,并随请求发送挑战令牌。然而,我们在首页做不同的是,如果挑战失败并在发布到HIBP端点时返回HTTP 401(您还会看到响应体“Invalid Turnstile token”),我们 meant 是回退到全页发布。当我们首次启动新网站时,这没有发生。但现在它发生了🙂

当全页发布回发生时,Cloudflare将呈现一个托管挑战。这更具侵入性,但也更可靠,然后将 serve 与您无论如何都会看到的相同结果,尽管通过全页加载。我们在深度链接的账户页面上实现相同的托管挑战逻辑,您可以在这里看到:https://haveibeenpwned.com/account/test@example.com

根据Cloudflare统计数据,大约82%的所有我们发出的挑战被成功解决:

在18%没有解决的中,许多将是由于Turnstile阻止的机器人 exactly 做它 meant 做的事。可能只有个位数的百分比请求是真实人类被阻碍,我们需要研究方法来降低这个数字,但至少回退位置现在改进了。如果您遇到问题,给网站一个好的刷新,看看您的情况,并在下面留下您的反馈。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计