手機號驗證
導包
import logging
log = logging.getLogger('django')
import re
import random
from .models import User
from settings import constant
from libs.yuntongxun.sms import CCP
from django.core.cache import cache
from .utils import get_jwt_by_user
from .utils import SMSRateThrottle
from rest_framework.response import Response
from .serializers import UserModelSerializer
視圖:user/views.py
class CheckMobileAPIView(APIView):
def get(self, request, *args, **kwargs):
mobile = request.query_params.get('mobile')
# mobile必須傳
if not mobile:
return Response({
'status': 2,
'msg': '缺失手機號',
})
# 校驗手機號是否合法
if not re.match(r'^1[3-9]\d{9}$', mobile):
return Response({
'status': 2,
'msg': '手機號有誤',
})
# 校驗手機是否已經註冊
try:
User.objects.get(mobile=mobile)
except: # 有異常表明未註冊
# log.info('手機未註冊')
return Response({
'status': 0,
'msg': '手機未註冊',
})
# log.info('手機已註冊')
return Response({
'status': 1,
'msg': '手機已註冊',
})
路由:user/urls.py
path("mobile/", views.CheckMobileAPIView.as_view()),
接口
http://api.luffy.cn:8000/user/mobile/?mobile=13355667788
獲取驗證碼
依賴
pip install django-redis
短信頻率組件:user/utils.py
from rest_framework.throttling import SimpleRateThrottle
class SMSRateThrottle(SimpleRateThrottle):
scope = 'sms'
def get_cache_key(self, request, view):
mobile = request.query_params.get('mobile')
# 疑問:給能轉換數字的字符串有異常
return "Throttle:%s" % mobile
配置:settings/dev.py
# 緩存
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"CONNECTION_POOL_KWARGS": {"max_connections": 100}
}
}
}
# 頻率組件
REST_FRAMEWORK = {
# ...
# 頻率模塊
'DEFAULT_THROTTLE_RATES': {
'sms': '1/m'
},
}
配置常量:settings/constant.py
# 短信失效時間 [秒]
SMS_EXPIRE_TIME = 300
# 短信模板 [測試階段只能爲1]
SMS_TEMPLATE_ID = 1
視圖:user/views.py
class SMSAPIView(APIView):
# 啓動頻率檢查
throttle_classes = [SMSRateThrottle]
def get(self, request, *args, **kwargs):
""" 發送短信 """
# 校驗手機
mobile = request.query_params.get('mobile')
if not re.match(r'^1[3-9]\d{9}$', mobile):
return Response('手機號有誤')
# 產生驗證碼
code = ''
for i in range(6):
code += str(random.randint(0, 9))
# redis緩存驗證碼
cache.set(mobile, '%s_%s' % (mobile, code), constant.SMS_EXPIRE_TIME)
# 發送驗證碼
try:
# send_template_sms("接受短信的手機號碼",["短信驗證碼", "短信有效期"], 短信模板ID)
result = CCP().send_template_sms(mobile, [code, constant.SMS_EXPIRE_TIME // 60], constant.SMS_TEMPLATE_ID)
if result == -1:
log.error("發送短信出錯!手機號:%s" % mobile)
return Response({'result': '短信發送失敗'})
except:
log.error("發送短信出錯!")
return Response({'result': '短信發送失敗'})
return Response({'result': '短信發送成功'})
路由
path('sms/', views.SMSAPIView.as_view()),
接口:用能夠收到短信的電話
http://api.luffy.cn:8000/user/sms/?mobile=13355667788
短信註冊
視圖:user/views.py
class RegisterCheckSMSAPIView(APIView):
def post(self, request, *args, **kwargs):
"""驗證碼註冊"""
mobile = request.data.get("mobile")
password = request.data.get("password")
sms = request.data.get("sms")
# 取出服務器驗證碼:redis緩存的
old_sms = cache.get(mobile)
# 校驗驗證碼:驗證碼的過時時間 redis與短信提醒方 統一了
if sms != old_sms:
return Response({
'status': 1,
'msg': '註冊失敗',
})
try:
# 若是手機號已經註冊,會拋異常,處理爲註冊失敗
user = User.objects.create_user(mobile=mobile, password=password, username=mobile)
except:
return Response({
'status': 1,
'msg': '註冊失敗',
})
return Response({
'status': 0,
'msg': '註冊成功',
"user": UserModelSerializer(user).data
})
路由
path('register/mobile/', views.RegisterCheckSMSAPIView.as_view()),
接口:用能夠收到短信的電話
# post請求
http://api.luffy.cn:8000/user/register/mobile/
# 數據
{
"mobile": "13355667788",
"password": "111111"
"sms": "325817",
}
短信登陸
二次封裝手動簽發JWT:user/utls.py
# 二次封裝手動簽發jwt
def get_jwt_by_user(user):
from rest_framework_jwt.settings import api_settings
try:
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
payload = jwt_payload_handler(user)
token = jwt_encode_handler(payload)
return token
except Exception:
return None
視圖:user/views.py
class LoginCheckSMSAPIView(APIView):
def post(self, request, *args, **kwargs):
mobile = request.data.get('mobile')
sms = request.data.get('sms')
old_sms = cache.get(mobile)
# 驗證碼校驗
if sms != old_sms:
return Response({'msg': '登錄失敗'})
# 獲取用戶
try:
user = User.objects.get(mobile=mobile)
except User.DoesNotExist:
return Response({'msg': '登錄失敗'})
return Response({
'token': get_jwt_by_user(user),
'user': UserModelSerializers(user).data
})
路由
path('login/mobile/', views.LoginCheckSMSAPIView.as_view()),
接口:用能夠收到短信的電話
# post請求
http://api.luffy.cn:8000/user/login/mobile/
# 數據
{
"mobile": "13355667788",
"sms": "325817",
}