91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Python編程如何使用DRF實現一次性驗證碼OTP

發布時間:2021-09-14 13:35:33 來源:億速云 閱讀:148 作者:小新 欄目:開發技術

這篇文章主要為大家展示了“Python編程如何使用DRF實現一次性驗證碼OTP”,內容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“Python編程如何使用DRF實現一次性驗證碼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

以上是“Python編程如何使用DRF實現一次性驗證碼OTP”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

锦州市| 介休市| 钟祥市| 宣恩县| 晋城| 砀山县| 扎赉特旗| 马公市| 钟祥市| 梨树县| 玛纳斯县| 广安市| 莲花县| 红河县| 扶风县| 虞城县| 德钦县| 宁化县| 安化县| 祥云县| 喀喇沁旗| 沂源县| 桂林市| 新乡县| 磐石市| 江源县| 乌鲁木齐县| 临漳县| 麟游县| 电白县| 辽宁省| 河津市| 五指山市| 云龙县| 垦利县| 定日县| 信宜市| 科技| 广昌县| 汾阳市| 乐安县|