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())  # 返回验证码图片
相关推荐
嘻哈baby14 分钟前
Redis高可用部署与集群管理实战
数据库·redis·bootstrap
DolphinDB智臾科技1 小时前
DolphinDB 面向金融交易与定价的统一数据模型
数据库·时序数据库
檀越剑指大厂1 小时前
时序数据库性能之战:金仓数据库如何在复杂场景下反超 InfluxDB?
数据库·时序数据库
计算机毕设VX:Fegn08952 小时前
计算机毕业设计|基于springboot + vue图书借阅管理系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
数据与人2 小时前
mongodb报错Sort exceeded memory limit of 104857600 bytes
数据库·mongodb
程序员鱼皮2 小时前
消息队列从入门到跑路,保姆级教程!傻子可懂
数据库·程序员·消息队列
C++业余爱好者2 小时前
SQL语言家族入门指南:标准SQL、T-SQL与PL/SQL详解
数据库·sql
白驹过隙^^2 小时前
OB-USP-AGENT安装使用方法
数据库·经验分享·网络协议·tcp/ip·github·ssl
计算机程序设计小李同学2 小时前
基于Python的在线零食购物商城系统的设计与实现
数据库·sqlite
Java爱好狂.3 小时前
Java面试Redis核心知识点整理!
java·数据库·redis·分布式锁·java面试·后端开发·java八股文