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())  # 返回验证码图片
相关推荐
莳花微语2 分钟前
Oracle 11G DataGuard GAP 修复过程(通过主库scn增备恢复)
数据库·oracle
petaexpress8 分钟前
云原生和数据库哪个好一些?
数据库·云原生·云原生和数据库哪个好·云原生和数据库
Cristiano永远是goat27 分钟前
数据库原理-期末复习基础知识第二弹
数据库
MXsoft6181 小时前
智能运维视角下的网络设备监测与数据分析
大数据·运维·数据库
冧轩在努力1 小时前
redis的应用--分布式锁
数据库·redis·分布式
2021-5-52 小时前
利用 Redis 与 Lua 脚本解决秒杀系统中的高并发与库存超卖问题
数据库·redis·lua
都要好好的O2 小时前
2.mysql 中一条更新语句的执行流程是怎样的呢?
数据库·mysql
夏子曦2 小时前
Redis——主从复制原理
数据库·redis·缓存
zxrhhm3 小时前
SQLServer中使用ISNULL替换为指定的替换值
数据库·sqlserver
zxguan3 小时前
MySQL 学习 之 数值计算精度问题
数据库·mysql·精度