urls.py
router = SimpleRouter()
router.register('', views.LoginAPIView, 'login')
urlpatterns = [
path('', include(router.urls)),
]
serializers.py
class BaseMethod(serializers.ModelSerializer):
def _sign_token(self, user):
"""签发token"""
import jwt
import datetime
from django.conf import settings
headers = {
'typ': 'jwt',
'alg': 'HS256',
}
payload = {
'user_id': user.pk,
'username': user.username,
'exp': datetime.datetime.utcnow() + datetime.timedelta(seconds=7),
}
# 盐
slat = settings.SECRET_KEY
token = jwt.encode(payload, key=slat, headers=headers)
return token
def validate(self, attrs):
user = self._get_user(attrs)
# 签发token
token = self._sign_token(user)
self.context['token'] = token
self.context['user'] = user
return attrs
def _get_user(self, *args, **kwargs):
raise NotImplementedError("._get_user() must be overridden.")
class CodeUserModelSerializer(BaseMethod):
code = serializers.CharField()
class Meta:
model = models.User
fields = ('telephone', 'code')
def _get_user(self, attrs):
"""
校验获取用户对象:
1. 判断用户手机号码是否符合格式
2. 判断用户手机号码是否存在数据中
3. 通过手机号码从缓存中获取用户的正确验证码
"""
from django.core.cache import cache
from django.conf import settings
telephone = attrs.get('telephone')
code = attrs.get('code')
if re.match(r'1[3-9][0-9]{9}$', telephone):
user = models.User.objects.filter(telephone=telephone).first()
utils.log.info(user)
if user:
# PHONE_CODE_KEY
telephone_key = settings.PHONE_CODE_KEY % telephone
cache_code = cache.get(telephone_key)
if code == cache_code:
# 注意: 用户登录以后, 验证码留在缓存中已经没有意义了!!
cache.set(telephone_key, '')
return user
raise ValidationError('验证码过期, 请重新发送!')
raise ValidationError("手机号码不存在!")
raise ValidationError('手机号码格式错误!')
views.py
class LoginAPIView(ViewSet):
...
@action(methods=('post',), detail=False)
def code_login(self, request, *args, **kwargs):
ser = serializer.CodeUserModelSerializer(data=request.data)
ser.is_valid(raise_exception=True)
token = ser.context['token']
user = ser.context['user']
return utils.APIResponse(token=token, username=user.username)