|
一、前端-登录校验、验证码
①登录页面HTML、验证码HTML{% load static %}<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<h1 class="text-center">登录</h1>
<div class="form-group">
<label for="username">用户名</label>
<input type="text" name="username" id="username" class="form-control">
</div>
<div class="form-group">
<label for="passowrd"></label>
<input type="password" name="password" id="password" class="form-control">
</div>
<div class="form-group">
<label for="">验证码</label>
<div class="row">
<div class="col-md-6 ">
<input type="text" name="code" id="id-code" class="form-control">
</div>
<div class="col-md-6" >
<img src="/get_code/" alt="" width="380" height="35" id="id_img">
</div>
</div>
</div>
<input type="button" class="btn btn-success" value="登录" id="login">
<span style="color: red" id="error"></span>
</div>
</div>
</div>②JS代码如何动态获取验证码<script>
// 实时获取验证码
$('#id_img').click(function (){
// 先获取到标签的src
let img_obj = $(this).attr('src');
// 在src后面加任意字符
$(this).attr('src',img_obj+='?')
})
//像后端发送ajax请求,并处理返回结果
$('#login').click(function (){
$.ajax({
url:'',
type:'post',
data:{
'username':$('#username').val(),
'password':$('#password').val(),
'code':$('#id-code').val(),
// 自己结合自己需求 合理选择,之前说的第三种csrf方式通过js文件的代码 在settings中配置一下,直接模板语法加载 load static即可
'csrfmiddlewaretoken':'{{ csrf_token }}'
},
success:function (args){
if(args.code==1000){
window.location.href =args.url
}else{
// 渲染错误信息
$('#error').text(args.msg)
}
}
})
})
</script>二、后端登录处理、验证码接口处理①登录返回接口def login(request):
if request.method == 'POST': # 可以用request.ajax方法
back_dic = {'code': 1000, 'msg': ''} # 注意用ajax方法一般都会设置一个字典给前端去处理
username = request.POST.get('username')
password = request.POST.get('password')
code = request.POST.get('code')
# 1 先校验验证码是否正确 自己决定是否忽略 统一转大写或者小写再比较
if request.session.get('code').upper() == code.upper(): # 后端代码发送给session,从session中获取验证码比对
user_obj = auth.authenticate(request, username=username, password=password)
if user_obj:
# 保存用户登录状态
auth.login(request,user_obj)
back_dic['url'] = '/home/'
else:
back_dic['code'] = 2000
back_dic['msg'] = '用户名或密码错误' # 因为我们用的auth模块,用户名和密码一起传入的,才会这样显示,如果想单独校验只有models自己单独去校验用户密码
else:
back_dic['code'] = 3000
back_dic['msg'] = '验证码错误'
return JsonResponse(back_dic)
return render(request, 'login.html')②验证码处理接口import random
from PIL import Image, ImageDraw, ImageFont"""
图片相关模块
pip3 install pillow
""""""
Image:生成图片
ImageDraw:能够在图片上乱涂乱画
ImageFont:控制字体的样式
"""from io import BytesIO, StringIO"""
BytesIO:临时存储数据,返回格式二进制
StringIO:临时存储数据,返回格式字符串
"""def get_random():
return random.randint(0, 255), random.randint(0, 255), random.randint(0, 255) # 自动会将这些用元组组织起来
def get_code(request):
# 推到步骤1:直接获取后端现成的图片二进制发送给前端
# with open(r'static/img/111.jpeg','rb')as f:
# data=f.read()
# return HttpResponse(data)
# 推到步骤2: 利用pillow模块动态产生图片
# img_obj= Image.new('RGB',(430,35),'red') # red可以换成三基色(255,255,255)
# img_obj= Image.new('RGB',(430,35),get_random())
# 先将图片信息保存起来
# with open('xxx.png','wb') as f:
# img_obj.save(f,'png')
# 再将图片去出来
# with open('xxx.png','rb') as f:
# data=f.read()
# return HttpResponse(data)
# 推导步骤3:文件存储繁琐IO操作效率低 借助于内存管理器模块,但是没有写上文字
# img_obj = Image.new('RGB', (430, 35), get_random())
# io_obj = BytesIO() # 生成一个内存管理器 你可以把这个看成一个文件句柄
# img_obj.save((io_obj),'png') 保存到内存管理器中
# return HttpResponse(io_obj.getvalue()) # 从内存管理器读取二进制的图片数据给前端
# 最终步骤:写图片验证码ImageDraw
img_obj = Image.new('RGB',(380,35),get_random())
img_draw = ImageDraw.Draw(img_obj) # 产生一个画笔对象
img_font = ImageFont.truetype('static/font/222.ttf',30) # 字体样式 大小
# 随机验证码 五位数的 大写 小写 数字
code=''
for i in range(5):
random_upper = chr(random.randint(65,90))
random_lower = chr(random.randint(97,122))
random_num = str(random.randint(0,9))
# 随机取出来一个
tmp=random.choice([random_lower,random_upper,random_num])
# 将产生的随机字符串写图片中去,一个一个写,要不然位置会重合在一起
img_draw.text((i*45+100,-2),tmp,get_random(),img_font)
# 字符串拼接
code += tmp
print(code)
# 随机的验证码在登录的视图函数里里面需要用到 要比对所以找地方存期哎 并且其他试图函数也能够拿得到
request.session['code'] = code
io_obj = BytesIO()
img_obj.save(io_obj,'png')
return HttpResponse(io_obj.getvalue())
|
|