短信驗證碼的設計與實現


准備:
  1.容聯雲通信注冊賬號並下載設置

  2.將yuntongxun文件夾復制到項目目錄下

短信驗證碼業務分析: 需要使用redis數據庫 配置文件里添加如下設置

CACHES = {
    "default": { # 默認的緩存配置
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/0",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    },
    # 我的需求是希望將session存儲在redis的1號庫
    "session": { # session后端
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/1",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    },
    "verify_code": { # 驗證碼
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/2",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    },
}

 

短信驗證碼后端接口設計:

1.請求方式
選項    方案
請求方法    GET
請求地址    /sms_codes/(?P<mobile>1[3-9]\d{9})/
請求參數:路徑參數和查詢字符串傳參
其中:mobile 是用路徑傳遞參數的, image_code 和 image_code_id 是用查詢字符串傳遞的參數.

2.參數名    類型    是否必傳    說明
mobile    string    是      手機號
image_code    string   是    圖形驗證碼
image_code_id    string   是    唯一編號

3.響應結果:JSON
字段    說明
code    狀態碼
errmsg    錯誤信息

 短信驗證碼實現 在視圖集文件里添加代碼

class SMSCodeView(View):

    def get(self, reqeust, mobile):
        # 避免頻繁發送短信驗證碼
        redis_conn = get_redis_connection('verify_code')

        send_flag = redis_conn.get('send_flag_%s' % mobile)
        if send_flag:
            return http.JsonResponse({'code': 400,
                                      'errmsg': '發送短信過於頻繁'})
     
        image_code_client = reqeust.GET.get('image_code')
        uuid = reqeust.GET.get('image_code_id')

        if not all([image_code_client, uuid]):
            return http.JsonResponse({'code': 400,
                                      'errmsg': '缺少必傳參數'})

        image_code_server = redis_conn.get('img_%s' % uuid)
        if image_code_server is None:
            return http.JsonResponse({'code': 400,
                                      'errmsg': '圖形驗證碼失效'})
        try:
            redis_conn.delete('img_%s' % uuid)
        except Exception as e:
            logger.error(e)

        image_code_server = image_code_server.decode()
        if image_code_client.lower() != image_code_server.lower():
            return http.JsonResponse({'code': 400,
                                      'errmsg': '輸入圖形驗證碼有誤'})

        sms_code = '%06d' % random.randint(0, 999999)
        logger.info(sms_code)

        # 創建管道對象: 
        pl = redis_conn.pipeline()

        # redis_conn.setex('sms_%s' % mobile, 300, sms_code)
        pl.setex('sms_%s' % mobile, 300, sms_code)

        # redis_conn.setex('send_flag_%s' % mobile, 60, 1)
        pl.setex('send_flag_%s' % mobile, 60, 1)

        # 執行管道: 
        pl.execute()

        CCP().send_template_sms(mobile, [sms_code, 5], 1)

        return http.JsonResponse({'code': 0,
                                  'errmsg': '發送短信成功'})

配置短信驗證碼的url  

urlpatterns = [
    re_path(r"^sms_codes/(?P<mobile>1[3-9]\d{9})/$", views.SMSCodeView.as_view()), 
]

 

短信驗證碼后端常見優化:

1. 如何避免頻繁發送短信驗證碼:
  在后端也要限制用戶請求短信驗證碼的頻率.
  60秒內只允許一次請求短信驗證碼.
  在 Redis 數據庫中緩存一個數值,有效期設置為60秒.

2. Redis服務端問題:
  如果Redis服務端需要同時處理多個請求,加上網絡延遲,
  那么服務端利用率不高,效率降低。
  解決方案:pipeline
  1. 創建redis請求管道
  2. 將操作redis的多個命令請求添加到管道隊列里
  3. 執行命令

3.發送短信是耗時操作,如果短信被阻塞,用戶響應會延遲,影響用戶界面倒計時延遲
  """
  CCP().send_template_sms(mobile, [sms_code, 5], 1)
  return http.JsonResponse({'code': 0, 'errmsg': '發送短信成功'})
  """
  解決方案:異步方案redis 和 Celey
  異步發送短信
  將發送短信業務和響應分開執行,將發送短信 從主業務中 解耦出來

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM