如何使用Django实现用户登录验证
最初开始搞用户登录验证的时候感觉没什么难的,不就是增删改查中的查询数据库么,但是还是遇到许多小问题,而且感觉在查询数据库的时候,要把前端的数据一条一条的进行比对,会导致我的代码很丑,而且方式很不智,所以进行了一些优化。
除此之外,我还加入了验证码的功能,同时使用form表单验证,功能应该是大致完善了。
check_code.py:
#!/usr/bin/python from PIL import Image,ImageDraw,ImageFont,ImageFilter import random import string ttf='C:\Windows\Fonts' def getCheckChar(): ran=string.ascii_letters+string.digits #ascii_letters 生成随机字母(大小写),digits生成数字 check_char='' for i in range(4): check_char+=random.choice(ran) print(check_char) return check_char def getImg(code): img=Image.new('RGB',(120,30),(255,255,255)) draw=ImageDraw.Draw(img) font = ImageFont.truetype('C:\Windows\Fonts\Monaco.ttf', 18) code=code color=random.randint(50, 150), random.randint(50, 150), random.randint(50, 150) for t in range(4): draw.text((28*t,0),code[t],color,font) # draw.text((60,0),code,color,font) #干扰点 chance=min(100, max(0, int(2))) for w in range(120): for h in range(30): tmp = random.randint(0, 100) if tmp > 100 - chance: draw.point((w, h), fill=(0, 0, 0)) #干扰线 for i in range(3): # 起始点 begin = (random.randint(0, 120), random.randint(0, 30)) # 结束点 end = (random.randint(0, 120), random.randint(0, 30)) draw.line([begin, end], fill=(0, 0, 0)) #图形扭曲参数 params = [1 - float(random.randint(1, 2)) / 100, 0, 0, 0, 1 - float(random.randint(1, 10)) / 100, float(random.randint(1, 2)) / 500, 0.001, float(random.randint(1, 2)) / 500 ] img = img.transform((120,30), Image.PERSPECTIVE,params, Image.BILINEAR) img=img.filter(ImageFilter.EDGE_ENHANCE_MORE) # img.save(''.join(code)+'.jpg','jpeg') return img if __name__ == '__main__': code=getCheckChar() getImg(code)
这个py文件我单独的写出来了,和views.py在同一目录下,作用是生成验证码,包括字符串和图片,要import的模块是pillow,对应的PIL
tty是字体文件,我用的是 Monaco.ttf ,自己下载的,注意要对应好它所在的位置
保存的话,如果你想单独用保存可以使用save方法保存,在views里我直接将图片保存在了内存里。
其他的都是pillow的正常操作了,什么大小啦滤镜啦,不赘述了。
views.py:
from django.shortcuts import render,HttpResponse,redirect from EMsystem import models from EMsystem import check_code from io import BytesIO def getcheck_code(request): code = check_code.getCheckChar() img = check_code.getImg(code) f = BytesIO() img.save(f, 'PNG') request.session['check_code']=code return HttpResponse(f.getvalue()) from django import forms from django.forms import fields #上传文件用 class FM(forms.Form): #这里要接受后端需要的,不需要的数据不会关注 teacher_id=forms.CharField(error_messages={'required':"不能为空"}) #表单中的name要与变量名一样 password=forms.CharField( min_length=5, error_messages={'required':"不能为空", 'min_length':'密码长度不小于5',}, ) def login_page(request): if request.method=="GET": return render(request,'login.html') if request.method=='POST': obj=FM(request.POST) if obj.is_valid(): print(obj.cleaned_data) check_dic=models.teacher_list.objects.filter(**obj.cleaned_data).first() if check_dic is None: return render(request,'login.html') else: checkcode=request.POST.get('checkcode') if checkcode.upper()==request.session['check_code'].upper(): request.session['userid']=obj.cleaned_data['teacher_id'] request.session['is_login']=True return render(request,'welcome.html') else: return render(request, 'login.html', {'err_checkcode': "验证码错误"}) else: return render(request,'login.html',{'obj':obj}) def welcome(request): if request.session.get('is_login',None): return render(request,'welcome.html') else: return redirect('/login/')
视图函数里写了四个函数:
getcheck_code:作用是生成验证码,同时保存到session中,图片保存到内存里并以HttpResponse提交到前端。
FM:作用是表单验证,这是django自带的form操作,用于检验前端的数据格式是否正确(前面的博文有介绍)。
login_page:作用是验证数据库和session中的验证码,这里直接使用了form的两个方法:
is_valid:检验字段是否正确
cleaned_data:将正确的结果以字典的形式返回
拿到cleaned_data之后直接怼到数据库里面filter一下,看是否为空,如果为空说明用户名密码不匹配,否则验证成功
check_dic=models.teacher_list.objects.filter(**obj.cleaned_data).first()
注意如果遇到session报 " KeyError "的问题就在terminal里执行以下两条命令,然后重启服务就可以了:
python manage.py makemigrations
python manage.py migrate
welcome:验证通过后访问的主页,如果直接访问该页面的话,会先检查is_login这个session是否为True(有关session的使用方法在前面的博文里)
验证成功之后返回welcome.html
HTML:
login.html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="login.html" method="POST"> {% csrf_token %} <p>username: <input type="text" name="teacher_id">{{ obj.errors.userid.0}}</p> <p>password:<input type="password" name="password">{{ obj.errors.password.0 }}<p> <p> 验证码: <input type="text" name="checkcode">{{ err_checkcode }} <span> <img src="/checkcode.html" onclick="chageCheckcode(this)"> </span> </p> <input type="submit" value="login"> </form> <script src="/static/jquery-1.12.4.js"></script> <script> function chageCheckcode(ths) { console.log(ths.src) ths.src=ths.src+'?' } </script> </body> </html>
urls.py:
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^welcome/',views.welcome),
url(r'^login/',views.login_page),
url(r'^checkcode.html$',views.getcheck_code),
]
这样就实现了登录认证功能