返回顶部
首页 > 资讯 > 后端开发 > Python >Python编程使用DRF实现一次性验证码OTP
  • 329
分享到

Python编程使用DRF实现一次性验证码OTP

2024-04-02 19:04:59 329人浏览 独家记忆

Python 官方文档:入门教程 => 点击学习

摘要

一次性验证码,英文是 One Time PassWord,简写为 OTP,又称动态密码或单次有效密码,是指计算机系统或其他数字设备上只能使用一次的密码,有效期为只有一次登录会话或很短

一次性验证码,英文是 One Time PassWord,简写为 OTP,又称动态密码或单次有效密码,是指计算机系统或其他数字设备上只能使用一次的密码,有效期为只有一次登录会话或很短如 1 分钟。OTP 避免了一些静态密码认证相关系的缺点,不容易受到重放攻击,比如常见的注册场景,用户的邮箱或短信会收到一条一次性的激活链接,或者收到一次随机的验证码(只能使用一次),从而验证了邮箱或手机号的有效性。

要实现的功能就是:

1、验证码是 6 位的数字和小写字母的组合。

2、有效期为 5 分钟,第二次发送验证码的必须在 1 分钟之后。

3、如果该邮箱/手机号已经注册,则不能发送注册验证码。

具体的实现逻辑就是:

1、先生成满足条件的验证码。

2、发送前验证,是否上次发送的验证码在 1 分钟之内?是否邮箱已经注册?,如果是,拒绝发送,并提示用户,如果否,发送验证码。

3、验证,是否是 5 分钟之内的验证码,是否正确,如果是,则放行。否则提示用户。

为了验证验证码及其时效,我们需要把发送验证码的时间和对应的邮箱记录下来,那么就需要设计一张表来存储。


class VerifyCode(models.Model):
    mobile = models.CharField(max_length=11, verbose_name="手机号", blank=True)
    email = models.EmailField(verbose_name="email", blank=True)
    code = models.CharField(max_length=8, verbose_name="验证码")
    add_time = models.DateTimeField(verbose_name='生成时间', auto_now_add=True)

1、生成验证码

第一个逻辑非常简单,可以直接写出代码:


from random import choice
 def generate_code(self):
 """
 生成 6 位数验证码,防止破解
 :return:
 """
 seeds = "1234567890abcdefghijklmnopqrstuvwxyz"
 random_str = []
 for i in range(6):
  random_str.append(choice(seeds))
 return "".join(random_str)

2、发送前验证

Django REST framework 框架的 Serializer 可以对 Models 里的每一个字段进行验证,我们直接在里面做填空题即可:


# serializers.py
class VerifyCodeSerializer(serializers.Serializer):
    email = serializers.EmailField(required=True)
    def validate_email(self, email):
        """
        验证邮箱是否合法
        """
        # 邮箱是否注册
        if User.objects.filter(email = email).count():
            raise serializers.ValidationError('该邮箱已经注册')
         # 验证邮箱号码合法
        if not re.match(EMAIL_REGEX, email):
            raise serializers.ValidationError('邮箱格式错误')
         # 验证码发送频率
        one_minute_age = datetime.now() - timedelta(hours=0, minutes=1, seconds=0)
        if VerifyCode.objects.filter(add_time__gt=one_minute_age, email=email).count():
            raise serializers.ValidationError('请一分钟后再次发送')
        return email
 

3、发送验证码

发送验证码,其实就是生成验证码并保存的过程,借助于 DjanGo REST framework 框架的 GenericViewSet 和 CreateModelMixin 即可实现 view 类,代码都有详细的注释,你很容易就看明白:


from rest_framework.response import Response
from rest_framework.views import status
from rest_framework import mixins, viewsets
class VerifyCodeViewSet(viewsets.GenericViewSet, mixins.CreateModelMixin):
    """
    发送验证码
    """
    permission_classes = [AllowAny] #允许所有人注册
    serializer_class = VerifyCodeSerializer #相关的发送前验证逻辑
    def generate_code(self):
        """
        生成6位数验证码 防止破解
        :return:
        """
        seeds = "1234567890abcdefghijklmnopqrstuvwxyz"
        random_str = []
        for i in range(6):
            random_str.append(choice(seeds))
        return "".join(random_str)
    def create(self, request, *args, **kwargs):
  # 自定义的 create() 的内容
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True) #这一步相当于发送前验证      
        # 从 validated_data 中获取 mobile
        email = serializer.validated_data["email"]
        # 随机生成code
        code = self.generate_code()
        # 发送短信或邮件验证码
        sms_status = SendVerifyCode.send_email_code(code=code, to_email_adress=email)
         if sms_status == 0:            
   # 记录日志
 
            return Response({"msg": "邮件发送失败"}, status=status.Http_400_BAD_REQUEST)
        else:
            code_record = VerifyCode(code=code, email=email)
            # 保存验证码
            code_record.save()   
            return Response(
                {"msg": f"验证码已经向 {email} 发送完成"}, status=status.HTTP_201_CREATED
            )
 

SendVerifyCode.send_email_code 的实现如下:


#encoding=utf-8
from django.core.mail import send_mail
class SendVerifyCode(object):
    @staticmethod
    def send_email_code(code,to_email_adress):
        try:
            success_num = send_mail(subject='xxx 系统验码', message=f'您的验证码是【[code]】。如非本人操作,请忽略。',from_email='xxxx@163.com',recipient_list = [to_email_adress], fail_silently=False)
            return success_num
        except:
            return 0

4、注册时验证

用户注册对于数据库来讲就是 User 类插入一条记录,也就是 User 的 view 类的 create 操作来实现注册。


from .serializers import UserReGISterSerializer, UserSerializer
class UserViewSet(viewsets.ModelViewSet):
    """
    api endpoint that allows users to be viewed or edited.
    """
    serializer_class = UserSerializer
 
    def get_serializer_class(self):
        if self.action == "create":
            # 如果是创建用户,那么用 UserRegisterSerializer
            serializer_class = UserRegisterSerializer
        else:
            serializer_class = UserSerializer
        return serializer_class

这个骨架好了以后,我们现在来编写 UserRegisterSerializer 类,实现注册时验证:


# serializers.py
class UserRegisterSerializer(serializers.ModelSerializer):
    # error_message:自定义错误消息提示的格式
    code = serializers.CharField(required=True, allow_blank=False, min_length=6, max_length=6, help_text='验证码',
                                 error_messages={
                                     'blank': '请输入验证码',
                                     'required': '请输入验证码',
                                     'min_length': '验证码格式错误',
                                     'max_length': '验证码格式错误',
                                 }, write_only=True)
    # 利用drf中的validators验证username是否唯一
    username = serializers.CharField(required=True, allow_blank=False,
                                     validators=[UniqueValidator(queryset=User.objects.all(), message='用户已经存在')])
    email = serializers.EmailField(required=True, allow_blank=False,
                                   validators=[UniqueValidator(queryset=User.objects.all(), message='邮箱已被注册')])
     # 对code字段单独验证(validate_+字段名)
    def validate_code(self, code):
        verify_records = VerifyCode.objects.filter(email=self.initial_data['email']).order_by('-add_time')
        if verify_records:
            last_record = verify_records[0]
            # 判断验证码是否过期
            five_minutes_ago = datetime.now() - timedelta(hours=0, minutes=5, seconds=0)  # 获取5分钟之前的时间
            if last_record.add_time < five_minutes_ago:
                raise serializers.ValidationError('验证码过期')
            # 判断验证码是否正确
            if last_record.code != code:
                raise serializers.ValidationError('验证码错误')
            # 不用将code返回到数据库中,只是做验证
            # return code
        else:
            raise serializers.ValidationError('验证码不存在')
    # attrs:每个字段validate之后总的dict
    def validate(self, attrs):
        # attrs['mobile'] = attrs['username']
        # 从attrs中删除code字段
        del attrs['code']
        return attrs
    class Meta:
        model = User
        fields = ('username', 'email', 'password', 'code')
        extra_kwargs = {'password': {'write_only': True}}
    def create(self, validated_data):
        user = User(
            email=validated_data['email'],
            username=validated_data['username']
        )
        user.set_password(validated_data['password'])
        user.save()
        return user

至此发送验证码的后端编码已经结束。

最后的话

一次性验证码(OTP)的逻辑简单,需要思考的是如何在 DRF 的框架中填空,填在哪里?这其实需要了解 DRF 的 ModelSerializer 类和 ViewSet 类之前的关系,在调用关系上,ViewSet 类调用 ModelSerializer 来实现字段的验证和数据保存及序列化,Serializers 类不是必须的,你可以完全自己实现验证和数据保存及序列化,只不过这样会导致 View 类特别臃肿,不够优雅,不易维护。

参考资料

[1]

Django REST framework: https://www.django-rest-framework.org

以上就是python编程使用DRF实现一次性验证码OTP的详细内容,更多关于Python编程DRF一次性验证码OTP的资料请关注编程网其它相关文章!

--结束END--

本文标题: Python编程使用DRF实现一次性验证码OTP

本文链接: https://lsjlt.com/news/135644.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Python编程使用DRF实现一次性验证码OTP
    一次性验证码,英文是 One Time Password,简写为 OTP,又称动态密码或单次有效密码,是指计算机系统或其他数字设备上只能使用一次的密码,有效期为只有一次登录会话或很短...
    99+
    2024-04-02
  • python如何实现三次密码验证
    小编给大家分享一下python如何实现三次密码验证,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!python是什么意思Python是一种跨平台的、具有解释性、编译性、互动性和面向对象的脚本语言,其最初的设计是用于编写自动化...
    99+
    2023-06-14
  • 如何使用Python实现极验验证码识别验证码
    这篇“如何使用Python实现极验验证码识别验证码”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“如何使用Python实现极验...
    99+
    2023-07-05
  • python实现三次密码验证的示例
    需求:Python实现三次密码验证,每次验证结果需要提示,三次验证不通过需要单独提示 代码如下: user = '张无忌' password = '12345678' confirm_flag = True f...
    99+
    2022-06-02
    python 密码 python 验证 python 密码验证
  • 使用Java实现验证码程序
    用java实现的给浏览器响应验证码程序。并且是实现了可以点击验证码图片换一张验证码。 最后边给出了完整的代码。 //首先定义一个自己的类并且去继承HttpServlet这个类 pub...
    99+
    2024-04-02
  • Python实现一个简单的验证码程序
      老师讲完random函数,自己写的,虽然和老师示例的不那么美观,智能,但是也自己想出来的,所以记录一下,代码就需要自己不断的自己练习,实战,才能提高啊!不然就像我们这些大部分靠自学的人,何时能学会。还有...
    99+
    2022-06-04
    验证码 简单 程序
  • python一次性密码如何实现
    今天小编给大家分享一下python一次性密码如何实现的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。一次性密码密码一次性密码密...
    99+
    2023-06-30
  • python密码学一次性密码的实现
    目录一次性密码密码为什么它是坚不可摧的?加密解密一次性密码密码的实现安装代码输出一次性密码密码 一次性密码密码是一种Vignere密码,包括以下功能; 这是一个牢不可破的密码.密钥与...
    99+
    2024-04-02
  • 使用ajax怎么实现一个验证码功能
    本篇文章给大家分享的是有关使用ajax怎么实现一个验证码功能,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。首先创建一个验证码:<%@ page con...
    99+
    2023-06-08
  • jQuery如何实现验证表单密码一致性
    这篇文章将为大家详细讲解有关jQuery如何实现验证表单密码一致性,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。jQuery 脚本<script type...
    99+
    2024-04-02
  • 怎么使用php实现验证码
    这篇文章主要介绍怎么使用php实现验证码,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!php实现验证码的方法:首先创建绘制验证码类,代码如“class Captcha {...}”;然后绘制图片页面;接着设置表单页面...
    99+
    2023-06-15
  • 使用python 怎么实现一个滑块验证码识别功能
    今天就跟大家聊聊有关使用python 怎么实现一个滑块验证码识别功能,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。普通滑动验证import timefrom se...
    99+
    2023-06-14
  • Python爬虫教程:200行代码实现一个滑动验证码
    Python爬虫教程:教你用200行代码实现一个滑动验证码做网络爬虫的同学肯定见过各种各样的验证码,比较高级的有滑动、点选等样式,看起来好像挺复杂的,但实际上它们的核心原理还是还是很清晰的,本文章大致说明下这些验证码的原理以及带大家实现一个...
    99+
    2023-06-02
  • Python使用captcha制作验证码的实现示例
    目录1 生成单张验证码图片并显示2 验证码图片的显示与保存3 批量生成验证码样本集在使用Keras搭建验证码识别模型时,需要大量的验证码图片。在这里,使用captcha模块生成验证码...
    99+
    2024-04-02
  • 使用java编写一个验证码生成功能
    使用java编写一个验证码生成功能?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。java 验证码的生成实现所谓验证码,就是将一串随机产生的数字或符号,生成一幅图片, 图片里...
    99+
    2023-05-31
    java ava
  • C#使用GDI+实现生成验证码
    一、概述 一般处理程序 ashx :它没有服务器控件,用response输出什么就是什么。 生成验证码原理:产生随机字符,并将字符生成为图片,同时储存到Session里去,然后验证用...
    99+
    2024-04-02
  • SpringBoot使用Kaptcha实现验证码的生成与验证功能
    当我们在项目中登录使用验证码的时候,不妨试试Kaptcha生成验证码,非常简单 1、首先,我们在pom.xml文件中引入kaptcha的maven依赖 <!-- kaptcha...
    99+
    2023-03-13
    SpringBoot实现Kaptcha验证码 SpringBoot Kaptcha验证码 SpringBoot验证码
  • AJAX 中怎么实现用户唯一性验证
    这篇文章给大家介绍AJAX 中怎么实现用户唯一性验证,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。 从数据库my中的username用户表里验证: che...
    99+
    2024-04-02
  • Python使用PIL库实现验证码图片的方法
    本文实例讲述了Python使用PIL库实现验证码图片的方法。分享给大家供大家参考,具体如下: 现在的网页中,为了防止机器人提交表单,图片验证码是很常见的应对手段之一。这里就不详细介绍了,相信大家都遇到过。 ...
    99+
    2022-06-04
    验证码 方法 图片
  • python简单验证码识别的实现过程
    目录1. 环境准备1.1 安装pillow 和 pytesseract1.2 安装Tesseract-OCR.exe1.3 更改pytesseract.py的ocr路径2. 测试识别...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作