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

回顾

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

使用zdppy_api开发简单接口回顾

python 复制代码
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生成验证码接口

python 复制代码
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这个方法

原来的方法

python 复制代码
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的两种方法

python 复制代码
import uuid

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

改进

增加一个uuid字符串。

python 复制代码
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个验证码的宽度是一样的,不太合理?

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

python 复制代码
image = ImageCaptcha(width=40 * num, height=height)

接口改造

增加key返回。

python 复制代码
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、我们现在有验证码了,该怎么校验验证码?

封装便捷接口

python 复制代码
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

使用便捷接口

python 复制代码
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

python 复制代码
from diskcache import Cache

cache = Cache()
cache.close()
with Cache(cache.directory) as reference:
    reference.set('key', 'value')
print(cache.get('key'))
相关推荐
hccee17 分钟前
C# IO文件操作
开发语言·c#
hummhumm22 分钟前
第 25 章 - Golang 项目结构
java·开发语言·前端·后端·python·elasticsearch·golang
杜小满26 分钟前
周志华深度森林deep forest(deep-forest)最新可安装教程,仅需在pycharm中完成,超简单安装教程
python·随机森林·pycharm·集成学习
J老熊32 分钟前
JavaFX:简介、使用场景、常见问题及对比其他框架分析
java·开发语言·后端·面试·系统架构·软件工程
zmd-zk1 小时前
flink学习(2)——wordcount案例
大数据·开发语言·学习·flink
好奇的菜鸟1 小时前
Go语言中的引用类型:指针与传递机制
开发语言·后端·golang
Alive~o.01 小时前
Go语言进阶&依赖管理
开发语言·后端·golang
花海少爷1 小时前
第十章 JavaScript的应用课后习题
开发语言·javascript·ecmascript
手握风云-1 小时前
数据结构(Java版)第二期:包装类和泛型
java·开发语言·数据结构
databook1 小时前
『玩转Streamlit』--布局与容器组件
python·机器学习·数据分析