4 个版本 (2 个破坏性更新)
0.3.0 | 2024年7月17日 |
---|---|
0.2.0 | 2023年12月25日 |
0.1.1 | 2023年12月19日 |
0.1.0 | 2023年12月19日 |
在 WebAssembly 中排名 #189
每月下载量 595 次
在 leptos-captcha 中使用
90KB
618 行 代码
spow - 服务器和客户端工作量证明 + WASM
为什么?
每个人都喜欢验证码,对吧?嗯,并不是那么喜欢。它们绝对是令人讨厌的,有时甚至人类也无法解决,因为某些东西只是处于边缘,或者服务器另一边只是认为你很愚蠢,给你另一个。
它们提供了一个绝对糟糕的用户体验,它们存在的唯一原因就是防止垃圾邮件。
工作量证明(PoW)解决的是类似的问题,但它对用户体验没有实际影响,但方式不同。它不是让用户解决一个谜题,而是让您的计算机为您解决。用户除了等待一小段时间直到谜题自动解决之外,没有其他事情可做。
背后的想法是,对于任何机器人或垃圾邮件发送者来说,为单个动作做这件事的成本实在太高了。如果您只是使用应用程序或网页的普通人,您不在乎,甚至不会注意到您的计算机时不时必须做的这项小工作量,但如果您是垃圾邮件发送者,同时在数百万个应用程序上同时这样做,这将是完全不可能的。
这里确实有一些非常复杂的解决方案,比如我非常喜欢的 Cloudflare Turnstile。然而,这个小小的 crate 使得在保持相同用户体验的同时,可以轻松自托管并集成到您的 API 中,而不需要任何外部依赖。
如何?
在后端,这不能更简单了
- 在应用程序启动时,您只需调用一次
Pow::init()
或Pow::init_random()
。这将初始化用于签名挑战的秘密,这样您就知道挑战是否确实来自您的后端,或者其他人只是自己生成的一个。 - 如果您想在某个时候为客户创建一个新的挑战,那么您只需要使用以下任一方法创建一个新的PoW:使用
Pow::new()
或Pow::with_difficulty()
。这将创建一个随机且唯一的PoW,可以将其转换为客户的挑战,使用以下任一方法:.build_challenge()
或.to_string()
。 - 将挑战字符串发送给客户端
- 客户端需要做一些工作来解决这个谜题。为此,您可以使用wasm或仅JS版本。这些位于
frontend/
文件夹中,可以直接在任何前端中使用。如果没有真正充分的理由不使用它,您应该始终使用wasm版本,因为它比仅JS快约20倍。这意味着您可以使用更高的难度而不会影响用户体验。 - 当您从客户端收到已解决的谜题时,只需使用
Pow::validate()
进行验证。这将...- 验证版本标签
- 验证难度(必须是10 - 99)
- 验证PoW的过期时间(在
Pow::new()
期间设置) - 验证挑战实际上来自同一后端且未被更改
- 使用给定的难度验证谜题结果本身
...就是这样。
在幕后,spow
使用修改后的扩展版Hashcat
PoW算法,该算法也被用于例如比特币区块链。
难度
难度是一个介于10和99之间的整数。默认值为20
。
每一步,解决谜题的时间将以指数级增加,而后端验证它的时间将始终保持不变,且与难度无关。
您想设置多高很大程度上取决于您的用例,您的应用程序将在哪里运行(强大的桌面机器、笔记本电脑或智能手机上的应用程序)以及您想让用户等待多久。
这些谜题的工作方式是,您可能会非常幸运并快速解决它,或者运气不佳,需要比平均值长得多。所有这些都取决于创建PoW时的随机值。为了找到合适的值,您应该在目标系统上测试很多不同的PoW,以找到合适的平均值。
此项目有一个bin目标,它实际上在后台执行此操作。您可以使用例如cargo run --release 20 100
运行它,它将解决100个难度为20的随机生成的谜题,并在最后打印出平均值。但请注意,后端代码的性能比浏览器中的代码要高得多。在首次测试中,浏览器中的wasm版本需要大约2.5 - 3倍的时间,这是在优化后的纯Rust代码中后端所需的时间。JS版本比wasm慢约20倍。
“examples
”文件夹包含了一个使用Svelte的小型前端演示。尽管它使用的是硬编码的挑战,但截至目前它只展示了如何解决谜题。它并不能很好地指示解决这些难度谜题所需的平均时间。
依赖项
约1.2-2.1MB
约41K SLoC