如何使用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)
View 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>
View Code

 

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),
]

这样就实现了登录认证功能

posted @ 2017-11-13 22:07  月夜夕烧雾雨  阅读(9709)  评论(1编辑  收藏  举报