Django实现登录失败5次锁定用户十分钟的完整方案
本文详细介绍如何在Django中实现登录安全机制:当用户连续5次输入错误密码时,系统自动锁定该账号10分钟。通过扩展Django默认User模型,增加登录状态、锁定时间及错误计数字段,并结合视图逻辑实现登录、锁定判断及退出清理。方案包含数据库设计、视图代码实现及测试流程,旨在为开发者提供简单有效的防暴力破解策略。
在Django开发过程中,为了实现登录失败后的用户锁定功能并记录锁定时间,我查阅了大量资料,但发现现有方案大多不够完善或可靠。因此,我决定自行设计一套解决方案。起初我考虑使用Redis,但为了贴近真实开发中逐步迭代的需求,我先构建了一个基础版本,后续再考虑拆分优化,这种渐进式开发方式更符合实际项目场景。
我的整体设计思路如下:
首先检查用户是否已登录,若已登录则提示“当前账号已在其他设备登录”。
若用户未登录,则判断其错误尝试次数是否少于6次。若满足条件,则校验密码:密码正确则登录成功,记录当前登录时间,清空错误次数,并更新登录状态为已登录。
若错误尝试次数大于等于6次,则提示账号已被锁定,并记录当前的错误次数。
最后,检查用户状态是否处于冻结(锁定)状态,若是则提示“账号已冻结”。
基于上述逻辑,我们设计相应的数据库模型。
class User(AbstractUser):
avatar=models.ImageField(upload_to='vaatar/%Y/%m',default='vaatar/default/pang')
qq=models.CharField(u'qq号码', max_length=20,blank=True)
mobile=models.CharField(u'手机号',max_length=11,blank=True,null=True,unique=True)
login_sta = models.CharField(u'登录是否锁定', max_length=2, default=0)
login_suo = models.DateTimeField(u'登录锁定时间')
pass_errnum=models.IntegerField(u'用户密码输入次数',default=0)
is_login = models.BooleanField(default=False)
class Meta:
verbose_name = u'用户'
verbose_name_plural = verbose_name
ordering=['-id']
def __str__(self) :
return self.username
这里的用户模型继承自Django默认的User模型,在此基础上扩展了必要的字段。
接下来,我们需要执行数据库迁移命令,同步模型变更到数据库中。
迁移完成后,我们可以查看数据库结构,确认新增字段已正确生成。

整体数据库结构确定后,我们开始设计登录视图。这里采用面向对象的方式编写登录视图类。
具体的视图实现代码如下:
from django.contrib.auth.hashers import make_password, check_password
from django.http import Http404, HttpResponseRedirect
from django.shortcuts import render, redirect
from django.views.generic.base import View
class LoginView(View):
def get(self,request):
return render(request, 'login.html')
def post(self,request):
next = request.META.get('HTTP_REFERER')
username=request.POST.get('username',None)
password=request.POST.get('password',None)
try:
user = User.objects.get(username= username)
if user.is_login==True:
return render(request, 'login.html', {'msg': '同时只能登陆一台设备!'})
if user.login_sta==True:
return render(request, 'login.html', {'msg': '账号已经冻结!'})
if (datetime.datetime.now()-user.login_suo).total_seconds() <600:
return render(request, 'login.html', {'msg': '账号锁定十分钟内不能登陆!'})
if user.pass_errnum>5:
user.login_suo=datetime.datetime.now()
return render(request, 'login.html', {'msg': '密码输入超过5次,用户锁定十分钟'})
if check_password(password,user.password) :
request.session['username'] = username
if '/logout' or '/reg' in next:
response = HttpResponseRedirect('/')
else:
response= HttpResponseRedirect(next)
user.last_login=datetime.datetime.now()
user.is_login=True
user.pass_errnum=0
user.save()
response.set_cookie('username', username, 3600)
return response
user.pass_errnum+=1
user.save()
return render(request, 'login.html', {'msg': '密码错误'})
except:
return render(request,'login.html',{'msg':'用户名不存在!'})
关于整体思路与实现细节,这里补充说明一点:之前的注册功能直接存储了明文密码,存在安全隐患。因此,我们改用Django内置的密码哈希机制进行加密和解密处理,以提升安全性。
接下来,我们进行程序功能测试。

当用户成功登录后,我们可以尝试在另一台设备上退出该账号,以验证登录状态的管理逻辑。

当我们连续输入6次错误密码后,系统会锁定该账号,并准确记录锁定时间。

此外,退出模块的设计逻辑如下:
class LogoutView(View):
def get(self,request):
try:
user = User.objects.get(username__exact=request.session['username'])
user.last_login=datetime.datetime.now()
user.is_login=False
user.save()
del request.session['username']
return render(request,'index.html')
except:
return HttpResponseRedirect('/')
用户执行退出操作时,系统会记录退出时间,并将登录状态更新为未登录。这样一个简单的限制用户登录时密码输入次数并锁定账号的功能便实现了。
通过上述步骤,我们成功解决了Django中限制用户登录时密码输入次数的问题。个人感觉该方案实现简单且效果良好。
需要注意的是,随着用户量增加,频繁查询数据库可能会带来压力。后续可以考虑将该逻辑优化至Redis服务器中,以提升性能。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









