Django验证码异常:提交验证时重复生成新验证码如何解决?
解决Django验证码验证中POST请求重新生成验证码的问题
问题根源很明确:Django的类视图每次HTTP请求都会创建一个全新的View实例。你在__init__方法里初始化的self.code,在GET请求时生成一次,到POST请求时会因为实例重新创建而生成新的验证码,这就导致用户输入的旧验证码和新生成的完全对不上,验证必然失败。
解决方案1:使用Session存储验证码(推荐,适合简单场景)
Session是和用户会话绑定的,跨请求会保留数据,刚好适合存储临时验证码:
@method_decorator(login_required, name='dispatch') class ConfirmEmail(View): def get(self, request): email = request.GET.get('email') # 在GET请求时生成验证码并存入session code = str(random.randint(1000, 9999)) request.session['confirmation_code'] = code send_mail( "Confirmation Code", f"Your confirmation code is: {code}", "your-sender-email@example.com", # 替换为实际发件邮箱 [email, ]) return render(request, "views/confirm_email.html") def post(self, request): confirmation_code = request.POST.get('confirmation_code', '').strip() # 从session中取出之前存储的验证码 stored_code = request.session.get('confirmation_code', '') if confirmation_code == stored_code: # 验证成功后删除session中的验证码,避免重复使用 del request.session['confirmation_code'] return redirect('home') else: return render(request, "views/confirm_email.html", {'error_message': 'Invalid confirmation code'})
解决方案2:使用数据库存储验证码(适合需要有效期管理的场景)
如果需要给验证码设置有效期,或者需要持久化记录,可以将验证码存在用户模型中:
from django.utils import timezone from datetime import timedelta @method_decorator(login_required, name='dispatch') class ConfirmEmail(View): def get(self, request): email = request.GET.get('email') user = request.user # 生成验证码并更新用户模型字段 code = str(random.randint(1000, 9999)) user.confirmation_code = code user.code_expires = timezone.now() + timedelta(minutes=10) # 设置10分钟有效期 user.save() send_mail( "Confirmation Code", f"Your confirmation code is: {code}", "your-sender-email@example.com", [email, ]) return render(request, "views/confirm_email.html") def post(self, request): confirmation_code = request.POST.get('confirmation_code', '').strip() user = request.user # 验证验证码正确性和有效期 if (confirmation_code == user.confirmation_code and user.code_expires is not None and user.code_expires > timezone.now()): # 验证成功后清空验证码相关字段 user.confirmation_code = '' user.code_expires = None user.save() return redirect('home') else: return render(request, "views/confirm_email.html", {'error_message': 'Invalid or expired confirmation code'})
注意:记得删除原来__init__方法里的self.code初始化代码,它已经没用了。
内容的提问来源于stack exchange,提问作者Brandon Thies
相关产品推荐
相关产品推荐

