分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 教程案例

博客园项目-登录(验证码,ajax提交数据,session和cookie)

发布时间:2023-09-06 01:41责任编辑:林大明关键词:验证码

前端页面

{% load static %}<!DOCTYPE html><html lang="zh-CN"><head> ???<meta charset="UTF-8"> ???<meta http-equiv="x-ua-compatible" content="IE=edge"> ???<meta name="viewport" content="width=device-width, initial-scale=1"> ???<title>Title</title> ???<link rel="stylesheet" href="{% static ‘bootstrap-3.3.7/css/bootstrap.min.css‘ %}"> ???<style> ???????body { ???????????background-color: #eeeeee; ???????} ???????h3{ ???????????padding-left: 100px; ???????} ???????.container{ ???????????margin-top: 300px; ???????} ???</style></head><body><div class="container"> ???<div class="row"> ???????<div class="col-md-6 col-md-offset-3"> ???????????<h3>请登录</h3> ???????????<form class="form-horizontal"> ???????????????{% csrf_token %} ???????????????<div class="form-group"> ???????????????????<label for="inputUser" class="col-sm-2 control-label">账号</label> ???????????????????<div class="col-sm-10"> ???????????????????????<input type="text" class="form-control" id="inputUser" placeholder="账号"> ???????????????????????<span class="help-block"></span> ???????????????????</div> ???????????????</div> ???????????????<div class="form-group"> ???????????????????<label for="inputPassword" class="col-sm-2 control-label">密码</label> ???????????????????<div class="col-sm-10"> ???????????????????????<input type="password" class="form-control" id="inputPassword" placeholder="Password"> ???????????????????????<span class="help-block"></span> ???????????????????</div> ???????????????</div> ???????????????<div class="form-group"> ???????????????????<label for="valid_code" class="col-sm-2 control-label">验证码</label> ???????????????????<div class="col-sm-5"> ???????????????????????<input type="text" class="form-control" id="valid_code" placeholder="验证码"> ???????????????????????<span class="help-block"></span> ???????????????????</div> ???????????????????<div class="col-sm-5"> ???????????????????????<img src="/get_valid_img/" ?width="200" height="40"> ???????????????????</div> ???????????????</div> ???????????????<div class="form-group"> ???????????????????<div class="col-sm-offset-2 col-sm-10"> ???????????????????????<input type="button" class="btn btn-primary btn-lg btn-block" value="登录"> ???????????????????????<span></span> ???????????????????</div> ???????????????</div> ???????????</form> ???????</div> ???</div></div><script src="{% static ‘jquery-3.2.1.min.js‘ %}"></script><script src="{% static ‘bootstrap-3.3.7/js/bootstrap.min.js‘ %}"></script><script> ???$(":button").click(function () { ???????$.ajax({ ???????????url:"/login/", ???????????type:"post", ???????????data:{ ???????????????"user":$("#inputUser").val(), ???????????????"pwd":$("#inputPassword").val(), ???????????????"valid_code": $("#valid_code").val(), ???????????????"csrfmiddlewaretoken":$("[name=‘csrfmiddlewaretoken‘]").val() ???????????}, ???????????success: function (data) { ???????????????var data = JSON.parse(data); ???????????????if (data.is_login){ ???????????????????location.href="/index/" ???????????????}else{ ???????????????????$(":button").next().text(data.error_msg).css("color","red") ???????????????????setTimeout(function () { ???????????????????????$(":button").next().text("") ???????????????????},1000) ???????????????} ???????????} ???????}) ???})</script></body></html>

可以看到用户访问登录页面时,在求情验证码图片时会访问/get_valid_img/,通过该url来得到验证码图片

用户的数据通过ajax提交到后端,当后端完成验证后,如果验证成后,则跳转到首页,如果失败,则将错误信息添加到页面上

生成随机验证码

def get_valid_img(request): ???# from utils.random_code import get_random_code ?# 局部模块导入不能用* ???# data = get_random_code() ???import random ???def get_random_color(): ???????return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) ???# 方式1: ???# f = open("car.jpg", "rb") ???# data = f.read() ???# f.close() ???# 方式2:将图片存到磁盘 ???# import PIL ???# from PIL import Image ???# from io import BytesIO ???# image = Image.new(mode="RGB", size=(120, 80), color=get_random_color()) ???# f = open("code.png", "wb") ???# image.save(f, "png") ???# f.close() ???# f = open("code.png", "rb") ???# data = f.read() ???# f.close() ???# 方式3:将图片放到内存 ???# import PIL ???# from PIL import Image ???# from io import BytesIO ???# image = Image.new(mode="RGB", size=(120, 80), color=get_random_color()) ???# f = BytesIO() ???# image.save(f, "png") ???# ???# data = f.getvalue() ???# 方式4: ???from PIL import Image ?# PIL模块可以通过下载pillow模块使用 ???from io import BytesIO ???from PIL import ImageDraw, ImageFont ?# 画笔 ???image = Image.new(mode="RGB", size=(120, 80), color=get_random_color()) ???draw = ImageDraw.Draw(image) ???font = ImageFont.truetype("static/fonts/kumo.ttf", size=32) ???temp = [] ???for i in range(5): ???????random_char = random.choice( ???????????[chr(random.randint(65, 90)), chr(random.randint(97, 122)), str(random.randint(0, 9))]) ???????draw.text((i * 24, 20), random_char, get_random_color(), font=font) ?# 参数分别为坐标,添加的字符串,颜色,字体 ???????temp.append(random_char) ???????# 为了让生成的验证码更具迷惑性,我们可以使用下面的方法给验证码图片中增加随机的点线等 ???# for i in range(80): ???# ????draw.point((random.randint(0,width),random.randint(0,height)),fill=get_random_color()) ???# ???# 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(40): ???# ????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() ???image.save(f, "png") ???data = f.getvalue() ???# 保存随机字符串 ???random_code_str = "".join(temp) ???request.session["random_code_str"] = random_code_str ???‘‘‘ ???1 生成随机字符串 ???2 响应set_cookie {"sessionid": "e21e12gg2d3sds"} ???3 在django_session表中插入一条记录 ???????session_key ????session_data ???‘‘‘ ???return HttpResponse(data)

由于验证码需要生成图片,此处我们导入了PIL模块(用来生成图片的模块)

先生成一个image对象,图片的颜色应该是随机的,我们定义一个生成3个随机数字组成元组的函数

import random ???def get_random_color(): ???????return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))

验证码中还需要有随机的字符串,此时我们从PIL模块中导入ImageDraw(画笔), ImageFont(字体)

首先生成一个字体对象,要先下载字体文件,并存放到项目中

然后通过该字体文件生成字体对象

font = ImageFont.truetype("static/fonts/kumo.ttf", size=32) ?# size为字体大小

然后往生成image图片中添加内容,内容应该为随机字符串,采用以下方法生成并添加到image图片中

draw = ImageDraw.Draw(image) ?# 画笔font = ImageFont.truetype("static/fonts/kumo.ttf", size=32)temp = []for i in range(5): ???random_char = random.choice( ???????[chr(random.randint(65, 90)), chr(random.randint(97, 122)), str(random.randint(0, 9))]) ???draw.text((i * 24, 20), random_char, get_random_color(), font=font) ???temp.append(random_char)

由于验证码图片只是发送给用户用来验证用的,没有必要保存到本地磁盘中,我们可以从io模块中导入BytesIO,在内存中生成空间来存放图片

from io import BytesIOf = BytesIO()image.save(f, "png")data = f.getvalue()

此时将data返回给页面,用户就可以看到验证码图片了

但是为了方便我们接收到用户输入的验证码后进行验证,我们需要保存此次生成验证码的内容

# 保存随机字符串random_code_str = "".join(temp)

现在我们需要考虑一个问题,用上面的方法保存验证码内容,如果一个用户先访问了登录页面,此时random_code_str被赋予了一个值,而这是另一个用户也访问了登录页面,这时random_code_str会被后一个值覆盖

那么前一个用户输入正确的验证码也无法验证成功了

在这种情况下,我们需要保证每一个用户都能保存住自己访问页面时验证码的值,可以考虑使用session

# 保存随机字符串random_code_str = "".join(temp)request.session["random_code_str"] = random_code_str

这里我们需要知道request.session做了什么:

1 生成随机字符串
2 响应set_cookie {"sessionid": "e21e12gg2d3sds"}
3 在django_session表中插入一条记录

如果用户访问时,已经有了cookie,那么这个操作会更新数据库django_session表中session_data的内容,而不会改变session_key等其它内容

点击更新验证码

当我们登录时,经常会遇到验证码看不清的情况,此时我们可以通过点击验证码图片进行刷新

这个功能可以通过前端JS实现

 ???// 验证码刷新 ???$("img").click(function () { ???????$(this)[0].src += "?" ???})

找到验证码图片的img标签,给他绑定一个点击事件,通过DOM对象的方法,在该图片的src后面加一个?号便可实现再次访问

后端验证

def log_in(request): ???response = {"is_login": False, "error_msg": ""} ???if request.method == "POST": ???????username = request.POST.get("user") ???????pwd = request.POST.get("pwd") ???????valid_code = request.POST.get("valid_code") ???????code_str = request.session.get("random_code_str") ???????if valid_code.upper() == code_str.upper(): ???????????user = auth.authenticate(username=username, password=pwd) ???????????if user: ???????????????response["is_login"] = True ???????????????auth.login(request, user) ?# 1 {"user_id": 1} 2 request.user=user ???????????else: ???????????????response["error_msg"] = "用户名密码错误" ???????else: ???????????response["error_msg"] = "验证码错误" ???????return HttpResponse(json.dumps(response)) ???return render(request, "login.html")

我们先校验验证码是否正确,在验证码正确的前提下再使用auth组件进行用户名和密码的验证

需要注意,当用户名密码也验证成功后,我们使用auth.login()方法写session,但由于此前访问验证码图片时已经在数据库中生成了session记录,该方法会先flush清除记录,再添加新的记录

所以这时我们会看到cookie中的sessionid的值变了,这里要和生成验证码时使用的request.session方法区分开来

博客园项目-登录(验证码,ajax提交数据,session和cookie)

原文地址:https://www.cnblogs.com/QQ279366/p/8424224.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved