从您的服务数据生成的CAPTCHA挑战
项目描述
OpenCaptcha
OpenCaptcha是一个完全自托管的CAPTCHA库,允许Web应用开发者根据其网站特定的数据生成挑战。这些挑战的信息以图形形式呈现给用户(通常为图表),然后用户需要根据图表中的信息从一组封闭选项中选择正确答案。
例如,一个分享关于冠状病毒爆发信息的网站可以生成一个条形图,显示当天活动病例最多的3个国家,并要求用户回答哪个国家病例最多。可用的挑战类型是托管网站可以配置的模板,如下所述。
安装
运行 pip install open-captcha
在您的网站上使用OpenCaptcha
要使用OpenCaptcha,网站的后端需要提供以下内容
- 数据表 模板可以使用以生成挑战。数据通常从网站的数据库中选择。
- 一组预建挑战模板的 配置。这通常以静态JSON配置文件的形式出现。每个配置项告诉open-captcha使用哪个模板以及如何配置它以从数据中生成独特的挑战。
当生成挑战时(见下文流程),它由三个部分组成
- 一个包含展示给用户的信息的
Challenge
结构。具体来说- 问题(字符串)。
- 一个展示给用户的图表(PNG图像)。
- 可能的答案列表(字符串)。
- 一个
ServerContext
结构,应在服务器上存储,并用于验证用户的答案。 - 一个
ChallengeID
,它是一个不透明的令牌,用于将Challenge
与其ServerContext
连接起来。
建议的后端流程如下
- 在启动时,构建一个
CaptchaGenerator
对象,向其提供数据表和您想要使用的模板配置。 - 调用
generator.generate_challenge()
,该函数随机选择一个模板,并使用它生成一个包含ChallengeId
、Challenge
和ServerContext
的三元组。 - 服务器应将
ServerContext
存储在某个缓存服务(例如redis)中,键为ChallengeId
。上下文应存储一个短的TTL(但足够长,以便合法用户能够回答问题)。 - 然后,将
Challenge
和ChallengeId
发送到客户端,客户端将它们展示给用户。一旦用户回答,用户的答案连同ChallengeId
一起发送回服务器进行验证。 - 服务器使用
ChallengeId
从缓存检索ServerContext
。如果未找到上下文(错误的令牌或TTL已过期),这视为验证失败。 - 服务器调用
generator.verify_response()
,传递用户的答案和ServerContext
。如果答案是正确的并且在指定的超时时间内接收,则该方法返回True。允许答案中存在可配置数量的错误。
示例流程可以在test_integration.py中找到,它以上述步骤的形式展示了单元测试。这些不包括调用服务器的逻辑:如何加载配置、如何从数据库检索数据、如何管理缓存和与客户端的通信。这些被故意省略,以便服务器开发者有最大的灵活性来实现这些方面。
通过添加新的挑战模板扩展库
OpenCaptcha附带了一些预定义的模板。这些可以通过在OpenCaptcha上工作的开发者随着时间的推移进行扩展,但也可以通过使用OpenCaptcha的服务器开发者进行扩展,以添加对他们的网站有意义的独特挑战类型。
要添加新的挑战类型,只需创建一个ChallengeTemplate
的子类并实现以下接口
- 类属性
config_name
应该是模板的名称,这是从配置中引用它的方式。 - 类的
__init__()
方法可以接受任何类型和数量的参数。这些在引用该模板的配置项中指定。典型的参数包括问题文本、从哪些数据表和列获取数据以及其他模板特定参数。 - 实现
generate_challenge()
方法。该方法接收数据,并应返回一个Challenge
对象和正确答案。