根本原因是表单提交时缺失captcha_0和captcha_1隐藏字段,或前端未用{{form.captcha}}正确渲染;二者缺一不可,否则服务端无法完成hashkey与response校验。

为什么 django-simple-captcha 的 CaptchaField 总是校验失败?
根本原因通常是表单提交时没把 captcha_0 和 captcha_1 两个隐藏字段一起提交,或者前端没正确渲染 captcha 字段。Django-simple-captcha 依赖这两个字段(hashkey 和 response)完成服务端校验,缺一不可。
实操建议:
- 确保表单类继承
forms.Form或forms.ModelForm,并在字段中显式声明CaptchaField() - 模板里必须用
{{ form.captcha }}渲染,不能手动拆解或只写<input>标签 - 检查浏览器开发者工具 Network 标签页,确认 POST 请求 payload 中包含
captcha_0和captcha_1两个键 - 如果用了 AJAX 提交,需手动序列化整个表单(
new FormData(formElement)),否则容易漏掉隐藏字段
如何自定义验证码图片尺寸和字符长度?
默认配置下验证码图片小、字符短,容易被 OCR 识别。修改需在 settings.py 中设置对应参数,且必须在 INSTALLED_APPS 添加 captcha 之后生效。
关键配置项:
-
CAPTCHA_LENGTH = 4:控制字符数(建议设为 4–6,设为 3 容易暴力穷举) -
CAPTCHA_IMAGE_SIZE = (120, 36):元组格式,宽高像素值(增大宽度可缓解字符粘连) -
CAPTCHA_FONT_SIZE = 24:字体大小,配合IMAGE_SIZE调整,避免文字溢出或过小 -
CAPTCHA_FOREGROUND_COLOR = "#333":前景色,避开纯黑/白以增加识别难度 - 注意:修改后需清空
captcha表(DELETE FROM captcha_captchastore;),否则旧 hashkey 可能无法匹配新规则
部署到 Nginx + Gunicorn 后验证码图片 404?
不是代码问题,而是静态文件路径没配对。django-simple-captcha 生成的图片是动态 URL(如 /captcha/xxx.png),不走 STATIC_ROOT,需要由 Django 视图响应,但反向代理常会错误拦截该路径。
Python 3.14.2是Python编程语言在2025年12月5日发布的稳定版本,属于3.14系列的第二个维护更新。该版本包含了18项修复,重点解决了多进程、数据类及正则表达式等模块的回归问题,并修复了CVE-2025-12084等安全漏洞。此版本标志着自由线程模式(移除GIL)正式获得官方支持,是Python发展的重要里程碑。
解决方法:
- Nginx 配置中添加排除规则:
location ^~ /captcha/ { proxy_pass http://backend; },确保该路径不被当作静态文件处理 - 确认
urls.py已包含path('captcha/', include('captcha.urls')) - Gunicorn 日志里若出现
Not Found: /captcha/xxx.png,说明请求根本没进 Django,一定是 Nginx 拦截了 - 本地开发用
runserver没问题,上线就 404?90% 是这个代理配置遗漏
为什么同一页面多个表单共用一个验证码总失败?
因为 django-simple-captcha 默认每个页面只维护一个有效 hashkey,后生成的会覆盖前一个。用户填第一个表单时验证码已失效,导致第二个提交必错。
应对方式:
- 给不同表单加独立命名空间:在
CaptchaField初始化时传参field_name='captcha_login'和field_name='captcha_register' - 对应地,在模板中用
{{ form.captcha_login }}和{{ form.captcha_register }}分别渲染 - 后台校验逻辑不受影响,但数据库会存多条记录,各自独立过期(默认 5 分钟)
- 不要试图复用同一个
CaptchaField实例 —— Django 表单字段是类属性,共享状态会导致冲突
验证码不是加个字段就完事,它涉及前后端字段协同、反代路由穿透、多实例隔离三个隐性关卡。漏掉任意一环,看起来“能显示”但实际无效。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










