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())  # 返回验证码图片
相关推荐
黑客K-ing5 分钟前
开源网络安全检测工具——伏羲 Fuxi-Scanner
网络·数据库·web安全
咸芝麻鱼31 分钟前
Django数据迁移出错,解决raise NodeNotFoundError问题
后端·python·django
尘浮生1 小时前
Java项目实战II基于Java+Spring Boot+MySQL的共享汽车管理系统(源码+数据库+文档)
java·数据库·spring boot·mysql·微信小程序·小程序·汽车
这样の我1 小时前
mongodb集群搭建
数据库·mongodb
SlothLu2 小时前
Debezium-KafkaDatabaseHistory
数据库·mysql·kafka·多线程·debezium·cdc·数据迁移
冷瞳2 小时前
Redis基本的全局命令
数据库·redis·缓存
2401_890666132 小时前
(免费送源码)计算机毕业设计原创定制:Java+JSP+HTML+JQUERY+AJAX+MySQL springboot计算机类专业考研学习网站管理系统
java·python·django·flask·node.js·html·课程设计
白云如幻2 小时前
SQL99版外连接
数据库·mysql
我们的五年3 小时前
【MySQL课程学习】:MySQL安装,MySQL如何登录和退出?MySQL的简单配置
linux·服务器·数据库·学习·mysql·adb
ProtonBase4 小时前
分布式 Data Warebase - 构筑 AI 时代数据基石
大数据·数据库·数据仓库·人工智能·分布式·数据分析·数据库系统