短信登录接口

后台

urls.py

path('mobile/login/', views.MobileLoginViewSet.as_view({'post': 'login'})),

serializers.py

import re
from django.core.cache import cache
class MobileLoginSerializer(serializers.ModelSerializer):
    # 覆盖
    mobile = serializers.CharField(required=True, write_only=True)
    # 自定义
    code = serializers.CharField(min_length=4, max_length=4, required=True, write_only=True)
    class Meta:
        model = models.User
        fields = ('id', 'username', 'icon', 'mobile', 'code')
        extra_kwargs = {
            'id': {
                'read_only': True,
            },
            'username': {
                'read_only': True,
            },
            'icon': {
                'read_only': True,
            },

        }

    # 手机号格式校验(手机号是否存在校验规则自己考量)
    def validate_mobile(self, value):
        if not re.match(r'^1[3-9][0-9]{9}$', value):
            raise exceptions.ValidationError('mobile field error')
        return value


    def validate(self, attrs):
        # 验证码校验 - 需要验证码与手机号两者参与
        mobile = self._check_code(attrs)
        # 多方式得到user
        user = self._get_user(mobile)
        # user签发token
        token = self._get_token(user)
        # token用context属性携带给视图类
        self.context['token'] = token
        # 将登录用户对象直接传给视图
        self.context['user'] = user
        return attrs

    def _check_code(self, attrs):
        mobile = attrs.get('mobile')
        code = attrs.pop('code')
        old_code = cache.get(settings.SMS_CACHE_KEY % {'mobile': mobile})
        if code != old_code:
            raise exceptions.ValidationError({'code': 'double code error'})
        else:
            # 验证码的时效性:一旦验证码验证通过,代表改验证码已使用,需要立即失效
            # cache.set(settings.SMS_CACHE_KEY % {'mobile': mobile}, '', -1)
            pass
        return mobile

    def _get_user(self, mobile):
        try:
            return models.User.objects.get(mobile=mobile)
        except:
            raise exceptions.ValidationError({'mobile': 'user not exist'})

    def _get_token(self, user):
        from rest_framework_jwt.serializers import jwt_payload_handler, jwt_encode_handler
        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)
        return token

views.py

class MobileLoginViewSet(ViewSet):
    # 局部禁用认证、权限组件
    authentication_classes = ()
    permission_classes = ()

    def login(self, request, *args, **kwargs):
        serializer = serializers.MobileLoginSerializer(data=request.data, context={'request': request})
        if serializer.is_valid():
            token = serializer.context.get('token')
            # 拿到登录用户,直接走序列化过程,将要返回给前台的数据直接序列化好给前台
            user = serializer.context.get('user')
            # 返回给前台的数据结果:id,username,icon,token
            result = serializers.MobileLoginSerializer(user, context={'request': request}).data
            result['token'] = token

            return APIResponse(result=result)
        return APIResponse(1, serializer.errors)
posted @ 2020-03-05 22:33  Jeff的技术栈  阅读(243)  评论(0编辑  收藏  举报
回顶部