短信登录接口

urls.py
1
path('mobile/login/', views.MobileLoginViewSet.as_view({'post': 'login'})),
serializers.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
from rest_framework import serializers
from rest_framework import exceptions
from django.conf import settings
from django.core.cache import cache
from . import models
import re

class MobileLoginSerializer(serializers.ModelSerializer):
# 覆盖
mobile = serializers.CharField(required=True, write_only=True)
# 自定义
code = serializers.CharField(min_length=6, max_length=6, 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('手机号不存在')
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(mobile)
if code != old_code:
raise exceptions.ValidationError({'code': '验证码不正确'})
else:
# 验证码的时效性:一旦验证码验证通过,代表改验证码已使用,需要立即失效
# cache.set(settings.SMS_CACHE_KEY % {'mobile': mobile}, '', -1)
return mobile

def _get_user(self, mobile):
try:
return models.User.objects.get(mobile=mobile)
except:
raise exceptions.ValidationError({'mobile': '手机号不存在'})

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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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(status=1,msg=result)
return APIResponse(status=0, msg=serializer.errors)
 

posted on 2020-12-16 20:40  Plyc  阅读(127)  评论(0编辑  收藏  举报

导航