Flask project 1 real combat: 2.3 Utiliser le code de vérification SMS sous le framework flask

Insérez la description de l'image ici

(Selon le contenu de l'émission en direct de l'enseignant)
  • Il existe de nombreuses plates-formes d'envoi de SMS. Cette fois, je prends la plateforme Ronglian Cloud pour envoyer des SMS à titre d'exemple.

1. Développement du module d'envoi de SMS

1. Utilisateurs enregistrés de Ronglian Cloud (inscription gratuite, authentification personnelle complète)

2. Créez une application et copiez l'ID APP et le TOKEN APP

Insérez la description de l'image ici
Insérez la description de l'image ici
Insérez la description de l'image ici

3. Modèle de SMS

  • Si l'application réelle a besoin de créer un modèle de message court, seul le test de développement n'a pas besoin de créer un nouveau modèle de message court, utilisez simplement le modèle de test fourni par le système
  • Insérez la description de l'image ici
    Insérez la description de l'image ici
  • Le projet utilise ce modèle comme exemple pour le développement et les tests
    Insérez la description de l'image ici

4. Ajoutez le numéro de test:

  • Il est inutile de créer un modèle de SMS, vous ne pouvez envoyer un SMS qu'au numéro de test
  • Pour le développement et les tests, ajoutez jusqu'à 3 numéros de téléphone mobile
    Insérez la description de l'image ici

5. Reportez-vous au document de développement pour développer le code de démonstration

5.1 Afficher les documents de développement

Insérez la description de l'image ici
Insérez la description de l'image ici
Insérez la description de l'image ici
Insérez la description de l'image ici

5.2 Copiez l'exemple d'appel, écrivez ronglianyun_SMS_demo.py

  • appId: ID donné par le système lors de la création de l'application (il apparaîtra également lors de l'édition de l'application)
  • accId, accToken: il suffit d'entrer dans la gestion de l'application pour copier, faire attention à la confidentialité
  • tid: ID de modèle créé par Ronglian Cloud Communication, test template id = "1"
  • datas: paramètres définis dans le modèle
    Insérez la description de l'image ici
from ronglian_sms_sdk import SmsSDK
 
accId = '容联云通讯分配的主账号ID'
accToken = '容联云通讯分配的主账号TOKEN'
appId = '容联云通讯分配的应用ID'
 
def send_message():
    sdk = SmsSDK(accId, accToken, appId)
    tid = '1'    # 应用是系统提供的开发测试模板及编号
    mobile = '手机号1,手机号2'
    datas = ('变量1', '变量2')  # 测试模板变量1:短信验证码,变量2:有效时间(分钟)
    resp = sdk.sendMessage(tid, mobile, datas)
    print(resp)  # resp 是string类型,还是json类型
    
send_message()

Insérez la description de l'image ici

Insérez la description de l'image ici

6. Développer un module d'envoi de SMS

  • Créez le package ronglianyun sous le package libs et compilez ccp_SMS.py
from ronglian_sms_sdk import SmsSDK
 
accId = '容联云通讯分配的主账号ID'
accToken = '容联云通讯分配的主账号TOKEN'
appId = '容联云通讯分配的应用ID'
 
def send_message():
    sdk = SmsSDK(accId, accToken, appId)
    tid = '1'    # 应用是系统提供的开发测试模板及编号
    mobile = '手机号1,手机号2'
    datas = ('变量1', '变量2') 
    resp = sdk.sendMessage(tid, mobile, datas)
	result=json.load(resp)
    if result["statusCode"]=="000000":
        return 0
    else:
        return -1
        
if __name__=="__main__":
    send_message()
   

7. Optimiser le module d'envoi de SMS de colis

  • Chaque fois qu'un message court est envoyé, le module d'envoi de SMS sera appelé et la classe SMSSDK sera instanciée, ce qui consomme beaucoup de ressources, donc le mode singleton doit être utilisé

7.1 Définir la classe singleton pour l'envoi de SMS

  • Définissez la classe CCP et remplacez la méthode __new __ ()
    • Déterminez d'abord s'il existe un attribut (_instance, personnalisé)
    • N'existe pas, appelez la méthode __new __ () de la classe parent super (), attribuez des valeurs aux attributs et transmettez les paramètres appropriés, puis définissez les attributs pour ajouter un SDK, qui est affecté à une instance de la classe SMS
    • Enfin renvoyer l'attribut
class CCP(object):
    """发送短信的单例类"""
    def __new__(cls,*args,**kwargs):
        if not hasattr(cls,"_instance"):
            cls._instance=super().__new__(cls,*args,**kwargs)
            cls._instance.sdk=SmsSDK(accId, accToken, appId)
        return cls._instance

7.2 Optimiser le module d'envoi de SMS

  • Utilisez des SMS singleton pour envoyer une optimisation de classe
  • Envoyer le paramétrage du code de vérification
from ronglian_sms_sdk import SmsSDK
import json

accId = '容联云通讯分配的主账号ID'
accToken = '容联云通讯分配的主账号TOKEN'
appId = '容联云通讯分配的应用ID'

class CCP(object):
    """发送短信的单例类"""

    def __new__(cls, *args, **kwargs):
        # 如果是第一次实例化,应该返回实例化后的对象,如果是第二次实例化,应该返回上一次实例化后的对象
        # 判断是否存在类属性 _instance
        if not hasattr(cls, "_instance"):
            cls._instance = super().__new__(cls, *args, **kwargs)
            cls._instance.sdk = SmsSDK(accId, accToken, appId)
        return cls._instance

    def send_message(self, tid, mobile, datas):
        sdk = self._instance.sdk
        # tid = '容联云通讯创建的模板ID'
        # mobile = '手机号1,手机号2'
        # datas = ('变量1', '变量2')
        # tid = '1'
        # mobile = '18908656327'
        # datas = ('2345', '5')
        resp = sdk.sendMessage(tid, mobile, datas)
        result = json.loads(resp)
        if result["statusCode"] == "000000":
            return 0
        else:
            return -1


if __name__ == "__main__":
    c = CCP()
    c.send_message("1", "18908656327", ("1234", "5"))    # 测试1号模板,手机号,(短信验证码,有效时间)

2. Conception de l'interface SMS

1. Analyse logique du code de vérification SMS

  • Tout d'abord, une fois que le code de vérification d'image est correct, une demande ajax de code de vérification SMS est lancée vers le backend
  • Une fois que le backend reçoit la demande, il reçoit et vérifie d'abord les paramètres
  • Paramètres de vérification:
    • Extrayez le code de vérification graphique de redis. Après l'extraction, supprimez le code de vérification graphique dans redis pour vous assurer que le code de vérification graphique n'est utilisé qu'une seule fois pour éviter les collisions de la bibliothèque.
    • Comparez si le code de vérification graphique passé est le même que le code de vérification retiré par redis, s'ils sont différents, renvoyez directement une erreur
    • Si c'est le cas, générez un code de vérification par SMS et enregistrez-le dans redis
    • Appelez le module d'envoi de SMS pour envoyer des SMS
    • Renvoyer l'état au frontal

Insérez la description de l'image ici

2. Document d'interface:

  • Nom de l'interface
  • la description
  • URL
  • Méthode de demande
  • Paramètres entrants
  • valeur de retour

Interface: Obtenez le code de vérification par SMS
Description: Accédez au front-end, vous pouvez obtenir l'
URL du numéro de code de vérification par SMS : /api/v1.0/image_codes/<re(r'1[345678[/d{9} ')>
Méthode de demande: GET
Paramètres entrants:

prénom Types de Dois tu La description
image_code Chaîne Oui Le numéro du code de vérification d'image
image_code_id Chaîne Oui uuid

valeur de retour:

prénom Types de Dois tu La description
errno Chaîne non code d'erreur
errmsg Chaîne non Contenu d'erreur

3. Définition de l'interface back-end (définition de la route):

  • La règle de paramètre de routage adopte une expression régulière personnalisée: <re ("regular expression")>
    • Ajouter r avant le caractère d'expression régulière (c'est un petit trou, il ne sera pas analysé selon l'expression régulière s'il n'est pas ajouté)
  • Récupérez les paramètres et assurez-vous que les deux paramètres doivent exister: all ([list]): Renvoie True si chaque élément de la liste n'est pas vide, sinon renvoie False
  • Retirez le code de vérification d'image de redis, s'il est anormal, renvoyez une erreur
  • Déterminez si le code de vérification d'image a expiré: la valeur retirée est Aucune, non obtenue, non enregistrée ou expirée
  • Supprimer le code de vérification d'image de redis: pour éviter les collisions de la bibliothèque, un code de vérification d'image ne peut être utilisé qu'une seule fois, qu'il soit vrai ou faux
  • Jugez si la vérification de l'image est correcte: ce sont des données binaires extraites de redis, qui doivent être codées, puis comparées aux paramètres transmis. Le code de vérification n'est pas sensible à la casse, vous devez donc changer la chaîne en majuscules ou minuscules .
  • Déterminez si le numéro de téléphone mobile a été enregistré: empêchez le téléphone mobile avec le numéro de téléphone mobile enregistré de se réenregistrer et vérifiez s'il existe un numéro de téléphone mobile dans la base de données
  • Générer le code de vérification par SMS: "% 06d"% random.randint (0, 999999): générer aléatoirement un nombre de 0-999999, ce qui n'est pas suffisant pour 6 chiffres, ajoutez 0 devant
  • Enregistrez le code de vérification SMS dans redis et définissez le délai d'expiration (défini comme une constante)
  • envoyer des messages
@api.route("/sms_codes/<re(r'1[345678]\d{9}'):mobile_code>")
def get_sms_code(mobile_code):
    """获取短信验证码"""
    print("mobile_code=",mobile_code)
    # 获取参数
    # 图片验证码
    image_code = request.args.get('image_code')
    # UUID
    image_code_id = request.args.get('image_code_id')

    print("image_code=",image_code)
    print("image_code_id=",image_code_id)


    # 校验参数,两个参数都不能为空
    if not all([image_code, image_code_id]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数不完整')

    # 业务逻辑
    # 从redis中取出验证码
    try:
        real_redis_code=redis_store.get('image_code_%s' % image_code_id)
    except Exception as e:
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg='redis数据库异常')

    # 判断图片验证码是否过期
    if real_redis_code is None:
        return jsonify(errno=RET.NODATA, errmsg='图片验证码失效')

    # 删除redis中的图片验证码
    try:
        redis_store.delete('image_code_%s' % image_code_id)
    except Exception as e:
        logging.error(e)

    # print(real_image_code)  b'RVMJ'
    # 与用户填写的图片验证码对比
    real_redis_code=real_redis_code.decode()
    if image_code.lower()!=real_redis_code.lower():
        return jsonify(errno=RET.PARAMERR, errmsg='图片验证码错误')

    logging.info("real_redis_code="+real_redis_code)

    # 判断手机号是否存在
    try:
        user = User.query.filter_by(mobile=mobile_code).first()
    except Exception as e:
        logging.error(e)
    else:
        if user is not None:
            # 表示手机号已经被注册过
            return jsonify(errno=RET.DATAEXIST, errmsg='手机号已经存在')

    # 生成短信验证码
    sms_code = "%06d" % random.randint(0, 999999)

    # 保存真实的短信验证码到redis
    try:
        redis_store.setex("sms_code_%s" % mobile_code, constants.SMS_CODE_REDIS_EXPIRES, sms_code)
    except Exception as e:
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg='保存短信验证码异常')

 # 发短信
    try:
        ccp = CCP()
        result = ccp.send_message(1,mobile_code, (sms_code, int(constants.SMS_CODE_REDIS_EXPIRES/60)))
    except Exception as e:
        logging.error(e)
        return jsonify(errno=RET.THIRDERR, errmsg='发送异常')

    # 返回值
    if result == 0:
        return jsonify(errno=RET.OK, errmsg='发送成功')
    else:
        return jsonify(errno=RET.THIRDERR, errmsg='发送失败')

4. Optimisation: évitez l'envoi fréquent de l'implémentation de la logique du code de vérification par SMS

  • Pour éviter la soumission malveillante et fréquente de demandes de vérification par SMS, il doit être limité à 1 application par minute

4.1 Analyse de réalisation logique

  • Une fois le code de vérification SMS envoyé avec succès, enregistrez le code de vérification SMS envoyé avec succès dans Redis et définissez l'heure de validité
  • Après avoir reçu l'application de code de vérification SMS envoyée par l'utilisateur, déterminez d'abord si la vérification graphique est correcte, puis déterminez s'il faut demander à nouveau dans le délai (vérifiez l'état d'envoi dans la requête redis, s'il existe, cela signifie que le la demande est à nouveau envoyée dans le délai)
  • Ensuite, vérifiez l'existence du numéro de téléphone mobile, ce qui peut empêcher les tests malveillants des informations des utilisateurs enregistrés
    Insérez la description de l'image ici

4.2 Optimisation du code et parfait

  • Extraire et vérifier send_flag
	# 判断手机号的操作
    try:
        send_flag=redis_store.get("send_flag_%s"% mobile_code)
    except Exception as e:
        logging(e)
    else:
        if send_flag is not None:
            return jsonify(errno=RET.RET.REQERR, errmsg='请求过于频繁')

 
  • Réécrire send_flag
 # 保存真实的短信验证码到redis
    try:
        redis_store.setex("sms_code_%s" % mobile_code, constants.SMS_CODE_REDIS_EXPIRES, sms_code)
        # 保存发送给这个手机号的记录
        redis_store.setex("send_flag_%s"% mobile_code, constants.SEND_SMS_CODE_EXPIRES, 1)
    except Exception as e:
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg='保存短信验证码异常')

5. Optimisation: pipeline redis

  • Dans le code ci-dessus, enregistrez le code de vérification SMS et l'état d'envoi à redis, et effectuez des opérations redis deux fois en même temps, ce qui peut être optimisé par pipeline
  • Pour le pipeline redis, voir «pipeline redis»
 # 保存真实的短信验证码到redis
    try:
        # redis管道
        pl = redis_store.pipeline()
        pl.setex("sms_code_%s" % mobile_code, constants.SMS_CODE_REDIS_EXPIRES, sms_code)
        # 保存发送给这个手机号的记录
        pl.setex('send_sms_code_%s' % mobile_code, constants.SNED_SMS_CODE_EXPIRES, 1)
        pl.execute()
    except Exception as e:
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg='保存短信验证码异常')

6. Citez dans le plan

  • Mettez cette fonction et le code de vérification d'image dans un seul fichier
from flask import Blueprint

api = Blueprint("api_1_0", __name__, url_prefix="/api/v1.0")

from . import demo,verify_code

3. Application du code de vérification graphique frontal (omis)

Je suppose que tu aimes

Origine blog.csdn.net/laoluobo76/article/details/110377427
conseillé
Classement