flask需借助captcha库生成图片验证码并绑定session存储答案。关键点:设secret_key启用session、存text.lower()到session['captcha_text']、响应头禁用缓存、前端加时间戳防图片缓存、verify_captcha中pop校验防重放并记录失败次数。

Flask 本身不内置验证码功能,必须借助第三方库(如 pytesseract + PIL 自研)或更稳妥的方案:用 captcha 库生成图片验证码,配合 session 存储答案。自己画字符+加噪点容易被 OCR 破解,生产环境不推荐。
用 captcha 库生成带 session 绑定的图片验证码
这是最省事且抗基础识别的方式。先安装:pip install captcha。关键点是:验证码文本必须存进 session,且设置过期时间;图片响应要禁用缓存,否则浏览器可能复用旧图导致核验失败。
-
session必须启用 secret_key:app.secret_key = 'your-secret-key',否则session写不进去 - 生成时用
ImageCaptcha实例调用generate_image(text),再把text.lower()存入session['captcha_text'] - 返回图片前设响应头:
response.headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0' - 字体文件路径若出错会静默回退到默认字体,建议显式指定:
ImageCaptcha(fonts=['/path/to/DejaVuSans.ttf'])
前端表单如何正确嵌入和提交验证码
前端不能只靠 <img src="/captcha"> 就完事。用户刷新页面时,src 不变会导致加载缓存图;提交时若没传验证码值,后端无法比对。
- 给
<img>加时间戳参数强制刷新:<img src="/captcha?r=" math.random> - 验证码输入框
<input name="captcha">的name必须和后端request.form.get('captcha')读取的键一致 - 提交前建议 JS 校验非空:
if (!input.value.trim()) { alert('请输入验证码'); return false; } - 不要用 GET 提交验证码字段,POST 更合理;后端统一用
request.form读取
verify_captcha() 函数里必须做的三件事
这个函数不是简单比字符串相等。它要处理大小写、空格、session 失效、超时重试等现实问题。
- 先检查
session.get('captcha_text')是否存在,不存在直接返回 False(说明用户没加载过验证码页,或 session 已过期) - 比对前统一转小写并
strip():user_input.lower().strip() == session.pop('captcha_text', '').lower().strip(),pop是关键——用完即删,防重放 - 如果比对失败,建议在 session 中记录错误次数:
session.setdefault('captcha_failures', 0); session['captcha_failures'] += 1,后续可据此限流 - 注意:Flask 默认 session 过期是 31 天,但验证码应更短,可在生成时手动设
session.permanent = True并配app.permanent_session_lifetime = timedelta(minutes=5)
真正麻烦的不是生成那几行代码,而是 session 生命周期管理、前端缓存对抗、以及用户反复输错后的体验控制。比如没清空 session['captcha_text'] 就跳转,下次加载页面可能还在用旧答案;又比如没设 Cache-Control,用户点“看不清”却刷出同一张图——这些细节一漏,功能就不可用。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











