21.手机接口

手机号验证

导包
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",
}

posted @ 2021-01-10 22:13  ABDM  阅读(140)  评论(0编辑  收藏  举报