Django - 验证码使用

验证码是一种区分用户是计算机还是人的公共全自动程序

可以防止:恶意破解密码、刷票、论坛灌水,有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试等

分类

当今验证码各种不同的类别很多,常见的如下:

  1. 普通型:随机多个(一般是4个)字母、数字和中文的图片,可能加一些干扰项

  2. 问答型:图片中显示一个问题,计算题、选择题四选一、问答题

  3. 拖动行为型:拖动一个小图片到一个拼图中

实现思路

大部分的验证码验证的思路都是这样的:

  1. 客户端发送获取验证码的请求

  2. 服务端接收到验证码请求后,生成对应的验证码和正确答案

  3. 服务端将验证码的正确答案保存到会话对象当中

  4. 服务端将验证码返回到客户端

  5. 客户端看到验证码后:

    • 如果看不清等原因,可以重新获取,那么就重新回到第1步
    • 正确显示后,输入答案,提交答案到服务端
  6. 服务端接收到验证码答案后,和保存在会话对象中的正确答案比对,正确就通过验证,失败则返回错误提示


实现

登录环境的搭建:

使用django的admin作为用户

python 复制代码
from django.shortcuts import render,redirect

from django.conf import settings
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required

# Create your views here.
from django.views import View

# 登录视图类
class LoginView(View):

    # 处理GET请求
    def get(self, request):
        login_err = request.session.get('login_err', None)  # 获取登录错误信息
        request.session.delete('login_err') # 删除登录错误信息

        return render(request, 'login.html',{'login_err':login_err})
    # 处理POST请求
    def post(self, request):
        username = request.POST.get('user', None)
        password = request.POST.get('pwd', None)
        user = authenticate(username=username, password=password)
        # 验证用户名和密码是否正确
        if user is not None:
            login(request, user) # 将用户信息添加到session中
            return redirect('index')
        else:
            request.session['login_err'] = '用户名或密码错误'
            return redirect('login')

# 登出视图函数
def logout_view(request):
    logout(request) # 清除session中的用户信息
    return redirect('login')


# 如果用户未登录重定向到login页面
@login_required(login_url='/login/')
def check_login(request):
    return render(request, 'index.html')

创建好登录之后就是验证码的生成

验证码图片生成

python 复制代码
import random
import os
from PIL import Image,ImageDraw,ImageFont,ImageFilter

def random_str(length=4):
  """ 随机字符串 默认长度 4
   :param length: 默认长度 4
   :return:
   """
  return ''.join(random.sample(string.ascii_letters, length))

# 生成颜色
def random_color():
  # RGB
  return random.randint(0,255),random.randint(0,255),random.randint(0,255)

# 生成验证码
def generate_captcha(width=160,height=40,length=4):
  # 创建一个空白图片
  image = Image.new('RGB',(width,height),color=(255,255,255))
  # 获取画布里的内容
  code = random_str()
  # 获取画笔
  draw = ImageDraw.Draw(image)
  # 随机颜色的填充
  for x in range(0,width,2):
    for y in range(height):
      draw.point((x,y),fill=random_color())
  # 获取字体文件
  font = ImageFont.truetype(os.path.join(os.path.dirname(__file__),'SIMHEI.TTF'),size=30)
  # 将内容写入图片
  for t in range(length):
    # 通过画笔工具写入内容
    draw.text((40*t+5,5),code[t],font=font,fill=random_color())  
  # 图片的模糊
  image = image.filter(ImageFilter.BLUR)
  # 返回图片,验证码
  return image,code
python 复制代码
from io import BytesIO

from django.http import HttpResponse
from django.shortcuts import render,redirect
from django.conf import settings
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required

from .create_caprcha import generate_captcha

# Create your views here.
from django.views import View

# 登录视图类
class LoginView(View):

    # 处理GET请求
    def get(self, request):
        login_err = request.session.get('login_err', None)  # 获取登录错误信息
        request.session.delete('login_err') # 删除登录错误信息

        return render(request, 'login.html',{'login_err':login_err})
    # 处理POST请求
    def post(self, request):
        username = request.POST.get('user', None)  # 获取用户名和密码
        password = request.POST.get('pwd', None)  # 获取用户名和密码
        input_code = request.POST.get('code', '')  # 获取用户输入的验证码
        right_code = request.session.get('captcha_code', '')  # 获取session中的验证码
        # 验证用户输入的验证码是否正确
        if input_code == right_code:
            user = authenticate(username=username, password=password)
            # 验证用户名和密码是否正确
            if user is not None:
                login(request, user)  # 将用户信息添加到session中
                return redirect('index')
            else:
                request.session['login_err'] = '用户名或密码错误'
                return redirect('login')
        else:
            request.session['login_err'] = '验证码不正确'
            return redirect('login')


# 登出视图函数
def logout_view(request):
    logout(request) # 清除session中的用户信息
    return redirect('login')


# 如果用户未登录重定向到login页面
@login_required(login_url='/login/')
def check_login(request):
    return render(request, 'index.html')



# 验证码测试视图函数
def captcha_test(request):
    img,code = generate_captcha()  # 生成验证码
    print(code)
    request.session['captcha_code'] = code  # 将验证码保存到session中
    buf = BytesIO()  # 创建一个BytesIO对象,用于存储验证码图片
    img.save(buf,'png')  # 将验证码图片保存到BytesIO对象中
    return HttpResponse(buf.getvalue())  # 返回验证码图片
相关推荐
GDAL1 小时前
Node.js v22.5+ 官方 SQLite 模块全解析:从入门到实战
数据库·sqlite·node.js
DCTANT2 小时前
【原创】国产化适配-全量迁移MySQL数据到OpenGauss数据库
java·数据库·spring boot·mysql·opengauss
AI、少年郎4 小时前
Oracle 进阶语法实战:从多维分析到数据清洗的深度应用(第四课)
数据库·oracle
赤橙红的黄4 小时前
自定义线程池-实现任务0丢失的处理策略
数据库·spring
DataGear5 小时前
如何在DataGear 5.4.1 中快速制作SQL服务端分页的数据表格看板
javascript·数据库·sql·信息可视化·数据分析·echarts·数据可视化
weixin_438335405 小时前
分布式锁实现方式:基于Redis的分布式锁实现(Spring Boot + Redis)
数据库·redis·分布式
码不停蹄的玄黓5 小时前
MySQL Undo Log 深度解析:事务回滚与MVCC的核心功臣
数据库·mysql·undo log·回滚日志
Qdgr_5 小时前
价值实证:数字化转型标杆案例深度解析
大数据·数据库·人工智能
数据狐(DataFox)5 小时前
SQL参数化查询:防注入与计划缓存的双重优势
数据库·sql·缓存
Arthurmoo5 小时前
Linux系统之MySQL数据库基础
linux·数据库·mysql