03 登录认证
知识点:
- JsonResponse()Django直接序列化,不用json.dumps()
- request.session['valid_code]=valid_code保存验证码
- 一次请求伴随多次请求,如静态文件请求和验证码请求
- PIL模块掌握
- session存储验证码
- 验证码刷新
登录界面html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Login</title> <link rel="stylesheet" href="/static/css/bootstrap.css"> </head> <body> <h3 class="text-center">登录页面</h3> <div class="container"> <div class="row"> <div class="col-md-6 col-lg-offset-3"> <form> <div class="form-group"> <label for="user">用户名:</label> <input type="text" id="user" class="form-control"> </div> <div class="form-group"> <label for="pwd">密码:</label> <input type="password" id="pwd" class="form-control"> </div> <div style="margin-top: 10px"> <input type="button" value="登录" class="btn btn-default login_btn pull-right"> </div> </form> </div> </div> </div> </body> </html>
生成验证码
验证码的前端实现
<div class="form-group"> <label for="">验证码:</label> <div class="row"> <div class="col-md-6"> <input type="text" class="form-control"> </div> <div class="col-md-6"> <img src="/get_validCode_img/" width="250px" height="35px"> </div> </div> </div>
后端实现
返回图片方式一,读取现有图片:
def get_validCode_img(request): #方式一 with open('img.png','rb') as f: data=f.read() return HttpResponse(data)
返回图片方式二,动态生成图片,存储在磁盘中:
def get_validCode_img(request): # 方式二 from PIL import Image import random def get_random_color(): return (random.randint(0,255),random.randint(0,255),random.randint(0,255)) img=Image.new("RGB",(250,35),color=get_random_color()) with open('validCode.png',"wb") as f: img.save(f,'png') with open('validCode.png','rb') as f: data=f.read() return HttpResponse(data)
返回图片方式三,动态生成图片,图片存储在内存中:
def get_validCode_img(request): # 方式三 from PIL import Image from io import BytesIO import random def get_random_color(): return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) img = Image.new("RGB", (250, 35), color=get_random_color()) f=BytesIO() img.save(f,'png') data=f.getvalue() return HttpResponse(data)
动态生成图片内容
def get_validCode_img(request): from PIL import Image,ImageDraw,ImageFont from io import BytesIO import random def get_random_color(): return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) img = Image.new("RGB", (250, 35), color=get_random_color()) draw=ImageDraw.Draw(img) font=ImageFont.truetype("static/font/JOKERMAN.ttf",size=20) for i in range(5): random_num=str(random.randint(0,9)) random_low_alpha=chr(random.randint(95,122)) random_upper_alpha=chr(random.randint(65,90)) char=random.choice([random_low_alpha,random_num,random_upper_alpha]) draw.text((i*40+30,3),char,get_random_color(),font=font) f = BytesIO() img.save(f, 'png') data = f.getvalue() return HttpResponse(data)
图片添加噪点
def get_validCode_img(request): from PIL import Image,ImageDraw,ImageFont from io import BytesIO import random def get_random_color(): return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) img = Image.new("RGB", (250, 35), color=get_random_color()) draw=ImageDraw.Draw(img) font=ImageFont.truetype("static/font/JOKERMAN.ttf",size=20) for i in range(5): random_num=str(random.randint(0,9)) random_low_alpha=chr(random.randint(95,122)) random_upper_alpha=chr(random.randint(65,90)) char=random.choice([random_low_alpha,random_num,random_upper_alpha]) draw.text((i*40+30,3),char,get_random_color(),font=font) width=250 height=35 for i in range(10): x1=random.randint(0,width) x2=random.randint(0,width) y1=random.randint(0,height) y2=random.randint(0,height) draw.line((x1,y1,x2,y2),fill=get_random_color()) for i in range(50): draw.point([random.randint(0,width),random.randint(0,height)],fill=get_random_color()) x = random.randint(0, width) y = random.randint(0, height) draw.arc((x,y,x+4,y+4),0,90,fill=get_random_color()) f = BytesIO() img.save(f, 'png') data = f.getvalue() return HttpResponse(data)
给验证码src添加一个“?”实现刷新验证码
<script> $("#valid_code_img").click(function () { $(this)[0].src+='?' }) </script>
保存验证码字符串
通过会话跟踪技术保存验证码
#会话跟踪技术保存valid_vode_str request.session['valid_code_str']=valid_code_str
def get_validCode_img(request): from PIL import Image,ImageDraw,ImageFont from io import BytesIO import random def get_random_color(): return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) img = Image.new("RGB", (250, 35), color=get_random_color()) draw=ImageDraw.Draw(img) font=ImageFont.truetype("static/font/JOKERMAN.ttf",size=20) valid_code_str=""#保存验证码 for i in range(5): random_num=str(random.randint(0,9)) random_low_alpha=chr(random.randint(95,122)) random_upper_alpha=chr(random.randint(65,90)) char=random.choice([random_low_alpha,random_num,random_upper_alpha]) valid_code_str+=char draw.text((i*40+30,3),char,get_random_color(),font=font) #会话跟踪技术保存valid_vode_str request.session['valid_code_str']=valid_code_str f = BytesIO() img.save(f, 'png') data = f.getvalue() return HttpResponse(data)
对验证码生成函数解耦
新建一个utils工具包,并创建calidCode模块,在模块中创建get_valid_code_img方法
from PIL import Image, ImageDraw, ImageFont from io import BytesIO import random def get_random_color(): return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) def get_valid_code_img(request): img = Image.new("RGB", (250, 35), color=get_random_color()) draw = ImageDraw.Draw(img) font = ImageFont.truetype("static/font/STSONG.ttf", size=20) valid_code_str = "" # 保存验证码 for i in range(5): random_num = str(random.randint(0, 9)) random_low_alpha = chr(random.randint(95, 122)) random_upper_alpha = chr(random.randint(65, 90)) char = random.choice([random_low_alpha, random_num, random_upper_alpha]) valid_code_str += char draw.text((i * 40 + 30, 3), char, (0, 0, 0), font=font) # 会话跟踪技术保存valid_vode_str request.session['valid_code_str'] = valid_code_str # 添加噪点 # width=250 # height=35 # for i in range(3): # x1=random.randint(0,width) # x2=random.randint(0,width) # y1=random.randint(0,height) # y2=random.randint(0,height) # draw.line((x1,y1,x2,y2),fill=get_random_color()) # for i in range(10): # draw.point([random.randint(0,width),random.randint(0,height)],fill=get_random_color()) # x = random.randint(0, width) # y = random.randint(0, height) # draw.arc((x,y,x+4,y+4),0,90,fill=get_random_color()) f = BytesIO() img.save(f, 'png') data = f.getvalue() return data
在view中导入相关函数
滑动验证
所需组件
验证用户名和密码
from django.contrib import auth
html页面中通过ajax技术请求,验证成功跳转到主页,验证错误显示错误信息
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Login</title> <link rel="stylesheet" href="/static/css/bootstrap.css"> </head> <body> <h3 class="text-center">登录页面</h3> <div class="container"> <div class="row"> <div class="col-md-6 col-lg-offset-3"> <form> {% csrf_token %} <div class="form-group"> <label for="user">用户名:</label> <input type="text" id="user" class="form-control"> </div> <div class="form-group"> <label for="pwd">密码:</label> <input type="password" id="pwd" class="form-control"> </div> <div class="form-group"> <label for="">验证码:</label> <div class="row"> <div class="col-md-6"> <input type="text" id="valid" class="form-control"> </div> <div class="col-md-6"> <img src="/get_validCode_img/" width="250px" height="35px" id="valid_code_img"> </div> </div> </div> <div style="margin-top: 10px"> <span class="has-error"></span> <input type="button" value="登录" id="login_btn" class="btn btn-default login_btn pull-right"> </div> </form> </div> </div> </div> </body> <script src="/static/js/jquery-3.3.1.js"></script> <script> //刷新验证码 $("#valid_code_img").click(function () { $(this)[0].src+='?' }); //登录验证 $("#login_btn").click(function () { $.ajax({ url:"", type:'POST', data:{ user:$("#user").val(), pwd:$("#pwd").val(), valid_code:$("#valid").val(), csrfmiddlewaretoken:$("input[name='csrfmiddlewaretoken']").val() }, success:function (data) { if(data.user){ location.href="/index/" } else{ $(".has-error").text(data.msg).css({'color':'red'}) } } }) }) </script> </html>
view视图中需导入的模块
from django.shortcuts import render,HttpResponse,redirect from django.http import JsonResponse from django.contrib import auth from django.contrib.auth.decorators import login_required
view视图中对用户提交的数据进行验证,验证成功后通过auth.login()来注册用户
def login(request): if request.method=="POST": response={'user':None,'msg':None} user=request.POST.get('user') pwd=request.POST.get('pwd') valid_code=request.POST.get('valid_code') valid_code_str=request.session.get('valid_code_str') if valid_code_str.upper()==valid_code.upper(): user=auth.authenticate(username=user,password=pwd) if user: auth.login(request,user)#注册session用户,request.user=当前登录用户 response['user']=user.username else: response['msg']='username or password error!' else: response['msg']="valid code error!" return JsonResponse(response) return render(request,'login.html')