手机号验证
导包
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",
}
手机接口