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())  # 返回验证码图片
相关推荐
竹笋常青12 分钟前
《流星落凡尘》
django·numpy
极客小张22 分钟前
基于STM32的智能充电桩:集成RTOS、MQTT与SQLite的先进管理系统设计思路
stm32·单片机·嵌入式硬件·mqtt·sqlite·毕业设计·智能充电桩
时差9531 小时前
【面试题】Hive 查询:如何查找用户连续三天登录的记录
大数据·数据库·hive·sql·面试·database
让学习成为一种生活方式1 小时前
R包下载太慢安装中止的解决策略-R语言003
java·数据库·r语言
秋意钟1 小时前
MySQL日期类型选择建议
数据库·mysql
Dxy12393102162 小时前
python下载pdf
数据库·python·pdf
桀桀桀桀桀桀3 小时前
数据库中的用户管理和权限管理
数据库·mysql
superman超哥4 小时前
04 深入 Oracle 并发世界:MVCC、锁、闩锁、事务隔离与并发性能优化的探索
数据库·oracle·性能优化·dba
用户8007165452004 小时前
HTAP数据库国产化改造技术可行性方案分析
数据库
engchina5 小时前
Neo4j 和 Python 初学者指南:如何使用可选关系匹配优化 Cypher 查询
数据库·python·neo4j