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'))
相关推荐
只想摆烂@10 分钟前
C# winfrom 如何多窗体优雅的回调方法
开发语言·c#
西猫雷婶12 分钟前
python画图|中秋到了,尝试画个月亮(球体画法)
开发语言·python
星迹日14 分钟前
C语言:结构体
c语言·开发语言·经验分享·笔记
William数据分析22 分钟前
[Python可视化]数据可视化在医疗领域应用:提高诊断准确性和治疗效果
python·信息可视化·数据分析
测试杂货铺23 分钟前
selenium元素定位:元素点击交互异常解决方法
自动化测试·软件测试·python·selenium·测试工具·职场和发展·单元测试
aWty_23 分钟前
机器学习--线性回归
python·算法·机器学习·线性回归
会敲代码的小张26 分钟前
设计模式-观察者模式
java·开发语言·后端·观察者模式·设计模式·代理模式
白如意i30 分钟前
在CentOS 7上安装Python 3并设置本地编程环境的方法
linux·python·centos
宗浩多捞30 分钟前
C++设计模式(更新中)
开发语言·c++·设计模式
肥猪猪爸2 小时前
“xi” 和 “dbscan” 在OPTICS聚类中是什么意思
python·机器学习·支持向量机·聚类