基于用户认证组件和Ajax实现用户登陆验证(图片验证码)
运用知识点:
- BootStrap实现页面设计
- auth认证组件登陆
- Ajax异步提交局部刷新校验
- forms组件制作提交单
- session储存验证码内容
- PIL图片制作工具制作验证码(制作躁点)
整个目录
stting 配置
# 因为自定义了 auth模块的 UserInfo表,所以django要设置默认表位置
AUTH_USER_MODEL = 'blog.UserInfo'
页面html
注意点:
- {% csrf_token %}
ajax必须传过去
- label for=”for属性可以让该label标签点击后
焦点到某个标签
- 点击验证码后从新访问一次路径,获得新图片 $(this)[0].src
+='?'
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>欢迎登陆</title>
<link rel="stylesheet" href="/static/blog/bs/css/bootstrap.css">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-6 col-lg-offset-3">
<form action="">
{% 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" class="valid_code form-control">
</div>
<div class="col-md-6">
<img width="263" height="34" id='code_img' src="/get_validCode_img/" alt="">
</div>
</div>
</div>
{# 后面加span 错误提示 #}
<input type="button" class="btn btn-default login_btn" value="登陆"><span class="error"></span>
</form>
</div>
</div>
</div>
</body>
<script src="/static/blog/js/jquery-3.3.1.min.js"></script>
<script>
//刷新验证码
$('#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_code').val(),
csrfmiddlewaretoken:$("[name='csrfmiddlewaretoken']").val() //token值
},
success:function (data) {
console.log(data)
if (data.user){
location.href='/index/' //js 跳转页面
}
else{
$('.error').text(data.msg).css({'color':'red', 'margin-left':'20px'})
}
}
})
})
</script>
</html>
验证码模块制作
注意点:
- 这种类似的功能性模块,封装起来
单独建立文件
夹存放utils
PIL制图模块
的使用:内含制图、画线、画点、写字等
import random
def get_random_color():
"""
生产随机 颜色
:return:
"""
color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
return color
def get_valid_code_img(request):
"""
生产随机验证码图片
:param request:
:return:
"""
# 图片生成模块 pip3 install pillow
from PIL import Image
# 画板工具
from PIL import ImageDraw
# 图片字体模块
from PIL import ImageFont
# 内存管理工具
from io import BytesIO
# 生成图片
width = 270
height = 40
img = Image.new('RGB', (width, height), color=get_random_color())
# 画板工具 写入文字
draw = ImageDraw.Draw(img)
# 字体设置
set_font = ImageFont.truetype('static/blog/font/AaMangXiaoGuo-2.ttf', size=24)
# 制作随机字符5位
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)) # 随机大写
# 随机选择一个
random_char = random.choice([random_num, random_low_alpha, random_upper_alpha])
# 写入字
draw.text((i*50+20, 5), random_char, get_random_color(), font=set_font) # 参数:位置,内容,颜色,字体
# 保存验证码字符串,用来比对用户输入
valid_code_str += random_char
# 制作噪点,直线和点
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())
# 储存验证码值到Session中(便于分离各个用户)
request.session['valid_code_str'] = valid_code_str
f = BytesIO() # 内存具柄
img.save(f, 'png')
data = f.getvalue()
return data
视图views
注意点:
- 验证码生成结果储存到
session
中,避免多用户之间混淆
from django.shortcuts import render, HttpResponse, redirect
from django.http import JsonResponse
from django.contrib import auth
def login(request):
if request.method == 'GET':
return render(request, 'login.html')
else:
# Json 返回登陆结果
response = {'user': None, 'msg': None}
# 提交的登陆post
user = request.POST.get('user')
pwd = request.POST.get('pwd')
valid_code = request.POST.get('valid_code') # 图片验证码
# 获取到session中的验证码值
valid_code_str = request.session.get('valid_code_str')
if valid_code.upper() == valid_code_str.upper(): # 不区分大小写
# 进行账号认证
user = auth.authenticate(username=user, password=pwd)
if user: # 有这个用户
auth.login(request, user) # request.user == 当前登陆对象
response['user'] = user.username
else:
response['msg'] = '用户名或密码错误!'
else:
response['msg'] = '验证码错误'
return JsonResponse(response)
def get_validCode_img(request):
"""
给予PIL模块动态生产验证码
:param request:
:return:
"""
from blog.utils.validCode import get_valid_code_img # 导入自己创建的工具文件utils
data = get_valid_code_img(request)
return HttpResponse(data)
def index(request):
return render(request, 'index.html')