登录界面中图片验证码的生成和校验

news2025/2/25 5:43:21

一、用pillpw生成图片验证码

1、安装pillow

pip install  pip install pillow

2、下载字体
比如:Monaco.ttf

3、实现生成验证码的方法
该方法返回一个img ,可以把这个img图片保存到内存中,也可以以文件形式保存到磁盘,还返回了验证码的文字。
在app01->utils->code.py, code.py内容如下:

import random
from PIL import Image,ImageDraw,ImageFont,ImageFilter
def check_code(width=120, height=30, char_length=5, font_file='Monaco.ttf', font_size=28):
    code = []
    img = Image.new(mode='RGB', size=(width, height), color=(255, 255, 255))
    draw = ImageDraw.Draw(img, mode='RGB')

    def rndChar():
        """
        生成随机字母
        :return:
        """
        return chr(random.randint(65, 90))

    def rndColor():
        """
        生成随机颜色
        :return:
        """
        return (random.randint(0, 255), random.randint(10, 255), random.randint(64, 255))

    # 写文字
    font = ImageFont.truetype(font_file, font_size)
    for i in range(char_length):
        char = rndChar()
        code.append(char)
        h = random.randint(0, 4)
        draw.text([i * width / char_length, h], char, font=font, fill=rndColor())

    # 写干扰点
    for i in range(40):
        draw.point([random.randint(0, width), random.randint(0, height)], fill=rndColor())

    # 写干扰圆圈
    for i in range(40):
        draw.point([random.randint(0, width), random.randint(0, height)], fill=rndColor())
        x = random.randint(0, width)
        y = random.randint(0, height)
        draw.arc((x, y, x + 4, y + 4), 0, 90, fill=rndColor())

    # 画干扰线
    for i in range(5):
        x1 = random.randint(0, width)
        y1 = random.randint(0, height)
        x2 = random.randint(0, width)
        y2 = random.randint(0, height)

        draw.line((x1, y1, x2, y2), fill=rndColor())

    img = img.filter(ImageFilter.EDGE_ENHANCE_MORE)
    return img, ''.join(code)

验证码的效果如下:
在这里插入图片描述

二、在登录界面加上验证码

1、添加一个验证码的url, 在urls.py 中增加:

from django.urls import path
from app01.views import user,depart,pretty,admin,account

urlpatterns = [
    path('login/account/',account.login),
    path('logout/',account.logout),
    path('image/code/',account.image_code),
]

2、在视图函数中增加验证码的处理
把生成后的图片保存再内存中,返回给页面,验证码的文字要先保存到session中,方便后面根用户输入的验证码进行校验。

from django.shortcuts import render,redirect,HttpResponse
from django import forms
from io import BytesIO
from app01.utils.code import check_code
def image_code(request):

    #调用pillow模块生成验证码
    img,code_string = check_code()

    #将验证码写入到自己的session中,一遍后续获取验证码进行校验
    request.session['image_code'] = code_string
    #给session设置60秒超时
    request.session.set_expiry(60)

    #将图片内容写入到内存中,from io import BytesIO
    stream = BytesIO()
    img.save(stream, 'png')

    return HttpResponse(stream.getvalue())

3、在登录页面增加验证码的输入框

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="{% static 'plugins/bootstrap-3.4.1/css/bootstrap.min.css' %}">
    <style>
        .account {
            width: 400px;
            border-radius: 5px;
            border: 1px solid #dddddd;
            box-shadow: 5px 5px 20px #aaa;

            margin-left: auto;
            margin-right: auto;
            margin-top: 100px;
            padding: 20px 40px;
        }
        .account h2 {
            margin-top: 10px;
            text-align: center;
        }
    </style>
</head>
<body>
<div class="account">
    <h2>用户登录</h2>
      <form  method="post" novalidate>
          {% csrf_token %}
                      <div class="form-group">
                        <label >{{ form.username.label }}</label>
                        {{ form.username}}
                      <span style="color:red">{{ form.username.errors.0 }}</span>
                      </div>
                        <div class="form-group">
                        <label >{{ form.passwd.label }}</label>
                        {{ form.passwd }}
                      <span style="color:red">{{ form.passwd.errors.0 }}</span>
                      </div>
          <div class="form-group">
              <label for="id_code">图片验证码</label>
              <div class="row">
                  <div class="col-xs-7">
                      {{ form.code }}
                      <span style="color: red">{{ form.code.errors.0 }}</span>
                  </div>
                  <div class="col-xs-5">
                      <img id="image_code"  src="/image/code/">
                  </div>
              </div>

          </div>
          <button type="submit" class="btn btn-primary">登录</button>
      </form>



</div>

<script src="{% static 'js/jquery-3.7.0.min.js' %}"></script>
<script src="{% static 'plugins/bootstrap-3.4.1/js/bootstrap.min.js' %}"></script>
</body>
</html>

登录界面效果如下:
在这里插入图片描述

3、登录的时候对验证码进行校验

获取到用户输入的验证码的值,再从session中取出之前保存的验证码的值,两者比较,如果一致就登录,不一致就重定向到登录界面,提示验证码错误。
还要注意的是,session在生成验证码的时间设置了过期时间是60s, 在登录的时候需要重写设置session的有效期。
在登录的视图函数修改如下:

def login(request):
    """用户登录"""
    if request.method == 'GET':
        form = LoginForm()
        return render(request,'login.html',{'form':form})

    form = LoginForm(data=request.POST)
    if form.is_valid():

        #验证码的校验
        # 这里为什么用pop 是因为cleaned_data获取到的是用户输入的所有信息,包括验证码,但是后面用户名密码根数据库校验的时候验证码是不在数据库的,所以这里就把验证码给去掉
        user_input_code = form.cleaned_data.pop('code')
        code = request.session.get('image_code',"")
        if code.upper() != user_input_code.upper():
            form.add_error("code","验证码错误")
            return render(request,'login.html',{'form':form})

        #print(form.cleaned_data)   #获取到的值是一个字典{'username': 'root', 'passwd': '4233c0d596c55f18df8c99ad1ad8af4f'}
        #校验数据库的用户名和密码
        admin_object = models.Admin.objects.filter(**form.cleaned_data).first()
        if not admin_object:
            form.add_error('passwd','用户名或密码错误')
            return render(request,'login.html',{'form':form})
        #用户名和密码正确
        #网站生成随机字符串; 写到用户浏览器的cookie中,再写入到session中
        request.session['info'] = {'id':admin_object.id,'name':admin_object.username}
        #重新设置session 的有效期,为24小时
        request.session.set_expiry(60*60*24)
        return redirect('/admin/list/')
    return render(request,'login.html',{'form':form})

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/863169.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

线上小程序电影票订单录入系统开发--Java、app、H5

在当今数字化时代&#xff0c;电影票订单的分销渠道和智能化分类已经成为电影产业不可或缺的一部分。为了满足这一需求&#xff0c;开发一款H5用户端电影票订单分销渠道智能分类小程序具有重要的实际意义。下面是该小程序开发的详细步骤。 一、需求分析 在开发H5用户端电影票…

用vim打开后中文乱码怎么办

Vim中打开文件乱码主要是文件编码问题。用户可以参考如下解决方法。 1、用vim打开.vimrc配置文件 vim ~/.vimrc**注意&#xff1a;**如果用户根目录下没有.vimrc文件就把/etc/vim/vimrc文件复制过来直接用 cp /etc/vim/vimrc ~/.vimrc2、在.vimrc中加入如下内容 set termen…

【选择排序】直接选择排序 与 堆排序

目录 1. 排序的概念&#xff1a; 2.选择排序的基本思想 3.直接选择排序 4.堆排序 1. 排序的概念&#xff1a; 排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。 稳定性&#xf…

MySQL_DQL语句(查询语句以及常用函数)

基础查询 不带条件的查询查询多个字段 语法&#xff1a; #查询指定字段的数据 SELECT 字段1, 字段2, 字段3 ... FROM 表名 ; #查询表中全部字段的数据 SELECT * FROM 表名 ;案例&#xff1a;查询表中所有信息数据 SELECT * FROM employee;案例&#xff1a;查询表中姓名和性别…

IntellIJ Idea 连接数据库-MySql

前言&#xff1a;可以用mariaDB工具&#xff0c;在本地创建服务器主机和数据库&#xff0c;而后用intellIJ Idea尝试连接 MariaDB创建数据库练习 1.IntellIJ Idea打开界面右侧Database工具&#xff0c;选择MySQL数据库。 2.填写数据库账号密码&#xff0c;地址端口号&#xff…

树莓派安装Ubuntu系统(无屏幕)

树莓派安装ubuntu系统 前言 软件需要: 1.方案一 win32diskimager-1.0.0-install.exe SDFormatterha Ubuntu镜像&#xff08;可以官网下载也可以清华源&#xff09; 方案二: 树莓派镜像烧录器 树莓派镜像烧录器直达下载 硬件需要: 64GB内存卡&#xff08;推荐Sanddisk Ultra&am…

程序员自由创业周记#6:劝退

程序员自由创业周记#6&#xff1a;劝退 photo-1547496614-154dee7fd157 这是一位程序员进行独立开发创业的记录&#xff0c;将分享创业过程中的所思所想以及收支明细。 劝退 如果一位程序员问我要不要进行独立开发创业&#xff0c;我100%会建议他不要冲动&#xff0c;因为这条路…

话题暴涨2344%,“妆面减负”成大势,小红书数据发掘潮流新趋势

Less is more&#xff0c;简约风吹遍时尚界&#xff0c;小红书上继Clean fit穿搭风热度高涨后&#xff0c;Clean makeup的妆容也逐渐走红&#xff0c;成为当下年轻人争相更风的时髦新趋势。 2023时尚新趋势&#xff0c;Clean fit→Clean makeup Clean makeup&#xff0c;即轻妆…

腾讯云轻量应用服务器端口怎么打开?图文方法来了

腾讯云轻量应用服务器端口放行在哪设置&#xff1f;在防火墙中可以开启端口号&#xff0c;腾讯云轻量应用服务器端口怎么开通&#xff1f;在轻量服务器管理控制台的防火墙中开启端口&#xff0c;如果是CVM云服务器在安全组中开通&#xff0c;腾讯云服务器网以轻量应用服务器开通…

MySQL数据库-基础篇

基础篇 一、SQL 分类 DDL-数据库操作 查询 创建表 数据类型 数值类型 字符串类型 日期类型 添加 修改 删除字段 修改表名 删除表 小结 DML-数据增删改 添加数据 修改数据 删除数据 小结 DQL-数据查询数据 基本查询 条件查询 聚合函数 分组查询 排序查询 分页查…

图片转表格方法分享,几个步骤轻松转换

在日常工作和学习中&#xff0c;我们经常会遇到需要将图片中的表格转换为可编辑的电子表格的情况。这时候&#xff0c;我们通常会手动一个一个地输入表格中的数据&#xff0c;费时费力&#xff0c;还容易出错。但是&#xff0c;其实有一些简单的方法可以帮助我们快速地将图片转…

关于npoi插入一条斜向上得线记录一下

在使用hssf可以直接按照行列插入。 HSSFWorkbook book new HSSFWorkbook();HSSFSheet sheet1 (HSSFSheet)book.CreateSheet("Sheet1");HSSFPatriarch patriarch (HSSFPatriarch)sheet1.CreateDrawingPatriarch();HSSFClientAnchor a1 new HSSFClientAnchor(255, …

k8s service

1、认识Service 程序在容器中、容器在Pod中&#xff0c;可以通过pod的ip来访问应用程序&#xff0c;但是podIP会随着创建销毁而改变。由此&#xff0c;Service出现&#xff1a; Service会对提供同一个服务的多个pod进行聚合&#xff0c;并且提供一个统一的入口地址。通过访问…

摄影照片后期处理工具:Athentech Perfectly Clear Complete

Athentech Perfectly Clear Complete 是一款强悍便捷的LR图像清晰化滤镜插件&#xff0c;可以让你想要更好的处理照片&#xff0c;Perfectly Clear完美清晰掌握了智能图像校正的技术原理 &#xff0c;可以在很短的时间里创造出高质量的照片&#xff0c;所以你可以回到做你真正的…

ISO/IEC技术标准-RFID

ISO/IEC技术标准规定了RFID有关技术特征、技术参数和技术规范&#xff0c;主要包括ISO/IEC 18000(空中接口参数)、ISO/IEC 10536(密耦合、非接触集成电路卡)、ISO/IEC 15693(疏耦合、非接触集成电路卡)和ISO/IEC 14443(近耦合、非接触集成电路卡)等。ISO/IEC的RFID技术标准构成…

nginx的rewrite功能和案例介绍

一.定义 二.作用 1.调整用户浏览的url&#xff0c;模板更规范 2.提升搜索引擎网站给予用户的体验&#xff0c;可以将动态的url伪装成静态地址提供服务 3.在网站更换新域名后&#xff0c;可以通过旧域名访问到新域名 4.便于根据特殊变量1、客户信息进行url调整 三.区分地址…

第四篇:组件更新:完整的 DOM diff 流程是怎样的?(上)

上一节课我们梳理了组件渲染的过程&#xff0c;本质上就是把各种类型的 vnode 渲染成真实 DOM。我们也知道了组件是由模板、组件描述对象和数据构成的&#xff0c;数据的变化会影响组件的变化。组件的渲染过程中创建了一个带副作用的渲染函数&#xff0c;当数据变化的时候就会执…

判断时间段是否重叠

1、逻辑公式 时间段1&#xff1a;start1&#xff08;开始时间&#xff09;&#xff0c;end1&#xff08;结束时间&#xff09; 时间段2&#xff1a;start2&#xff08;开始时间&#xff09;&#xff0c;end2&#xff08;结束时间&#xff09; 重叠条件为&#xff1a;start1 <…

ad+硬件每日学习十个知识点(30)23.8.10 (SDIO端口扩展器TXS02612RTWR,模数转换器ADC121C027)

文章目录 1.cpu->SDIO端口扩展器->SD卡槽->SD卡(当然也可以反向读取)2.SDIO端口扩展器介绍3.SDIO端口扩展器TXS02612RTWR4.SD卡槽5.什么是模数转换器&#xff1f;6.I2C模数转换器ADC121C0277.模数转换方案 1.cpu->SDIO端口扩展器->SD卡槽->SD卡(当然也可以反…

win11(不符合要求)安装方法

win11&#xff08;不符合要求&#xff09;安装方法&#xff1a; 注意&#xff01;这样安装win11可能会导致文件丢失&#xff0c;请备份重要文件&#xff08;会删除c盘很多文件&#xff0c;可以在c盘Windows.old文件夹恢复。 第一步、下载win11ISO镜像&#xff1a;恰到好处系统…