zdppy+vue3+onlyoffice文档管理系统实战 20240820上课笔记 Python验证码框架的研究

回顾

  • 1、封装了一个zdppy_captcha框架用于生成验证码
  • 2、实现了生成base64格式的验证码
  • 3、想要生成一个和zdppy_api能够天然结合的接口,使得使用更简单

使用zdppy_api开发简单接口回顾

import api


async def get_captcha(req):
    return api.resp.success()


app = api.Api(
    routes=[
        api.resp.get("/captcha", get_captcha)
    ]
)

if __name__ == '__main__':
    app.run()

接口请求:
在这里插入图片描述

使用zdppy_api生成验证码接口

import api
import zdppy_captcha as captcha


async def get_captcha(req):
    code, img = captcha.get_base64(4)
    return api.resp.success({
        "img": img,
    })


app = api.Api(
    routes=[
        api.resp.get("/captcha", get_captcha)
    ]
)

if __name__ == '__main__':
    app.run()

简单的分析

目前我们想要生成验证码图片是比较简单的,但是怎么验证?

  • 1、如何区分是哪个用户的?

目前的结构,很难区分是哪个用户的,不过我们之前分析过一种比较靠谱的方案。

  • 在生成code和img的同时,生成一个key,给前端返回key和img,后端根据key记录code,前端传递key和code,然后进行对比。key必须保证唯一性!!!

改进get_base64这个方法

原来的方法

def get_base64(num=4, width=160, height=60):
    """
    生成base64格式的随机字符串
    建议校验的时候不区分大小写
    :param num: 字符串中验证码的个数
    :param width: 验证码图片的宽度
    :param height: 验证码图片的高度
    :return: 真实值,base64图片字符串
    """
    # 生成随机字符串
    code = random.sample(base_str, num)

    # 生成图片验证码对象
    image = ImageCaptcha(width=width, height=height)

    # 第三种使用方式:生成图片验证码BytesIO
    data = image.generate(code)

    # 转换为base
    base64_str = base64.b64encode(data.getvalue()).decode('utf8')

    # 返回
    code = "".join(code)
    return code, base64_str

python生成uuid的两种方法

import uuid

print(uuid.uuid4().hex)
print(str(uuid.uuid4()).replace("-", ""))

改进

增加一个uuid字符串。


def get_base64(num=4, width=160, height=60):
    """
    生成base64格式的随机字符串
    建议校验的时候不区分大小写
    :param num: 字符串中验证码的个数
    :param width: 验证码图片的宽度
    :param height: 验证码图片的高度
    :return: 真实值,base64图片字符串
    """
    # 生成随机字符串
    code = random.sample(base_str, num)

    # 生成图片验证码对象
    image = ImageCaptcha(width=width, height=height)

    # 第三种使用方式:生成图片验证码BytesIO
    data = image.generate(code)

    # 转换为base
    base64_str = base64.b64encode(data.getvalue()).decode('utf8')

    # 返回
    key = uuid.uuid4().hex
    code = "".join(code)
    return key, code, base64_str

改进2

验证码的宽度现在是固定,4个验证码和6个验证码的宽度是一样的,不太合理?

应该根据验证码的个数动态的扩展宽度。

image = ImageCaptcha(width=40 * num, height=height)

接口改造

增加key返回。

import api
import zdppy_captcha as captcha


async def get_captcha(req):
    key, code, img = captcha.get_base64(4)
    return api.resp.success({
        "key": key,
        "img": img,
    })


app = api.Api(
    routes=[
        api.resp.get("/captcha", get_captcha)
    ]
)

if __name__ == '__main__':
    app.run()

问题分析

  • 1、这个接口实际上可以封装为便捷的接口
  • 2、我们现在有验证码了,该怎么校验验证码?

封装便捷接口

def get(success, num=4):
    """
    获取zdppy_api生成验证码的接口
    :param num: 验证码的个数
    :param success: api.resp.success 是zdppy_api框架中统一返回成功结果的方法
    :return:
    """
    async def get_captcha(req):
        key, code, img = get_base64(num)
        return success({
            "key": key,
            "img": img,
        })

    return get_captcha

使用便捷接口

import api
import zdppy_captcha as captcha

app = api.Api(
    routes=[
        api.resp.get("/captcha", captcha.zdppy_api.get(api.resp.success))
    ]
)

if __name__ == '__main__':
    app.run()

简单的总结

目前获取验证码的接口暂时这样基本就够用了。

但是,我们还缺少校验验证码的方法以及接口。

首先我们需要实现校验验证码的方法。

如何校验验证码是否正确?

获取验证码有什么返回值?

  • key:唯一标识
  • code:验证码的真实值
  • img:base64格式的图片

如何校验?

  • 传入key和code,如果和库里面的key和code相同,则校验通过!!

要实现这个思路,问题比较多:

  • 1、用什么库去存储key和code?
  • 2、怎么进行对比
  • 3、key需要做过期处理,我们不可能让它一直生效!!!

怎么存储key和code?

用一个全局的字典。

我们知道接口的请求一般都是多线程或者多协程,会产生并发。python的字典,是不是并发安全的?

不是!!!

但是我们对字典的操作通常是复合操作(插入、删除、更新),这些步骤并不是原子性的。在多线程抢占解释器锁时(特别是多核CPU的机器中),就可能会导致数据不一致。因此,字典类型在多线程环境中并不是线程安全的,因为它的操作不满足原子性,需要额外的同步机制(如锁)来保证在多线程环境下的正确使用。

找到了一个值得研究的库

https://grantjenks.com/docs/diskcache/tutorial.html

from diskcache import Cache

cache = Cache()
cache.close()
with Cache(cache.directory) as reference:
    reference.set('key', 'value')
print(cache.get('key'))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Python私教

创业不易,请打赏支持我一点吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值