ToB企服应用市场:ToB评测及商务社交产业平台

标题: 登录注册接口搭建 [打印本页]

作者: 愛在花開的季節    时间: 2022-11-3 20:16
标题: 登录注册接口搭建
登录接口分析

登录分为多方式登录和验证码登录方式
多方式登录
  1. 1)前台提供账号密码,账号可能是 用户名、手机号、邮箱等
  2. 接口:
  3. 后台只需要提供一个多方式登录接口即可 - 多方式登录接口
复制代码
多方式登录接口
前端输入完账号和密码,点击登录,向后端发送请求进行校验用户登录数据
urls.py
  1. from django.urls import path,re_path,include
  2. from rest_framework.routers import SimpleRouter
  3. from user import views
  4. router = SimpleRouter()
  5. router.register('',views.LoginView,'login')
  6. urlpatterns = [
  7.     path('',include(router.urls)),
  8. ]
复制代码
views.py
  1. from rest_framework.viewsets import ViewSet
  2. from user import serializers
  3. from luffyapi.utils.response import APIResponse
  4. from rest_framework.decorators import action
  5. class LoginView(ViewSet):
  6.     # 密码方式登录接口
  7.     @action(methods=['POST'],detail=False) # 加入action装饰器,自动生成路由
  8.     def login(self,request,*args,**kwargs):
  9.         # 把前端传入的用户登录数据传入序列化器
  10.         ser = serializers.UserModelserialize(data=request.data)
  11.         # 判读传入的数据是否合法
  12.         if ser.is_valid():
  13.             # 合法获取token和用户名
  14.             token =ser.context['token']
  15.             username = ser.context['user'].username
  16.             # 然后返回给前端
  17.             return APIResponse(token=token,username=username)
  18.         else:
  19.             return APIResponse(code='0',msg=ser.errors)
复制代码
serializes.py
  1. from rest_framework import serializers
  2. from user import models
  3. from rest_framework.exceptions import ValidationError
  4. class UserModelserialize(serializers.ModelSerializer):
  5.     username = serializers.CharField() # ?
  6.     class Meta:
  7.         model = models.UserInfo
  8.         fields = ['username','password','id']
  9.         extra_kwargs = {
  10.             'id':{'read_only':True},
  11.             'password': {'write_only': True},
  12.         }
  13.     def validate(self, attrs):
  14.         # 多种方式登录
  15.         user = self._get_user(attrs)
  16.         # 签发token
  17.         token = self._get_token(user)
  18.         # 放到context中,我在视图函数中可以取出来
  19.         self.context['token'] = token
  20.         self.context['user'] = user
  21.         return attrs
  22.     # 校验前端发来的数据
  23.     def _get_user(self, attrs):
  24.         # 获取前端发送的数据
  25.         username = attrs.get('username')
  26.         password = attrs.get('password')
  27.         import re
  28.         # 校验前端的用户是否为手机号、邮箱、用户名登录
  29.         if re.match('^1[3-9][0-9]{9}$',username):
  30.             user = models.UserInfo.objects.filter(telephone=username).first()
  31.         elif re.match('^.+@.+$',username):
  32.             user = models.UserInfo.objects.filter(email=username).first()
  33.         else:
  34.             user = models.UserInfo.objects.filter(username=username).first()
  35.         # 用户名存在,则校验密码
  36.         if user:
  37.             ret = user.check_password(password)
  38.             if ret:
  39.                 return user
  40.             else:
  41.                 raise ValidationError('密码错误')
  42.         else:
  43.             raise ValidationError('用户名不存在')
  44.     # 签发token函数,前面加一个_暗示内部使用的
  45.     def _get_token(self,user):
  46.         from rest_framework_jwt.serializers import jwt_payload_handler,jwt_encode_handler
  47.         pyload = jwt_payload_handler(user) #通过user对象获取pyload
  48.         token = jwt_encode_handler(pyload) #通过pyload获取token
  49.         return token
复制代码
验证码登录

验证码可以保存在redis里,也可以保存在缓存里
  1. 1)前台提供手机号和验证码完成登录
  2. 接口:
  3. 前台填完手机号,往后台发送校验手机号的请求,如果存在继续,不存在提示注册 - 手机号存在与否接口
  4. 前台点击发送验证码,将手机再次发送给后台,后台将手机号通知给第三方,发送短信 - 手机验证码接口
  5. 前台点击登录提交手机号与验证码,完成验证码登录 - 验证码登录接口
复制代码
手机号是否存在的接口设计
  1.     # 校验手机号是否存在接口
  2.     @action(methods=['GET'], detail=False)
  3.     def check_telephone(self, request, *args, **kwargs):
  4.         telephone = request.GET.get('telephone')
  5.         if not re.match('^1[3-9][0-9]{9}$',telephone):
  6.             return APIResponse(code=0,msg='手机号不合法')
  7.         try:
  8.             models.UserInfo.objects.get(telephone=telephone)
  9.             return APIResponse()
  10.         except:
  11.             return APIResponse(code=0,msg='手机号不存在')
复制代码
发送验证码接口
  1. from luffyapi.libs.tx_msg import get_code,send_message # 导入封装好的短信接口
  2. from django.core.cache import cache # 导入缓存
  3. from django.conf import settings
  4.     # 发送验证码接口
  5.     @action(methods=['GET'], detail=False)
  6.     def send(self,request,*args,**kwargs):
  7.         telephone = request.GET.get('telephone')
  8.         if not re.match('^1[3-9][0-9]{9}$',telephone):
  9.             return APIResponse(code=0,msg='手机号不合法')
  10.         code = get_code() #获取随机验证码
  11.         result = send_message(telephone,code)
  12.         # 将验证码保存到缓存中备用,参数分别是key,value,过期时间秒
  13.         # 这个telephone可以有标识一点,在settings进行配置一下
  14.         cache.set(settings.CACHE_MSG % telephone,code,180)
  15.         # 如果result返回true
  16.         if result:
  17.             return APIResponse(msg='验证码发送成功')
  18.         else:
  19.             return APIResponse(code=0,msg='验证码发送失败')
复制代码
短信发送频率限制
写一个throttlings.py
  1. from rest_framework.throttling import BaseThrottle, SimpleRateThrottle
  2. # 写一个类继承SimpleRateThrottle
  3. class TimeThrottling(SimpleRateThrottle):
  4.     scope = 'sms'
  5.     def get_cache_key(self, request, view):
  6.         telephone = request.query_params.get('telephone')
  7.         return self.cache_format%{'scope':'sms','ident':telephone} # 以手机号返回不太好,换一种不易重名的返回做限制
复制代码
在settings里配置一下频率
  1. REST_FRAMEWORK = {
  2.     'DEFAULT_THROTTLE_RATES': {
  3.         'sms': '1/m'  # 一分钟访问1次
  4.     }
  5. }
复制代码
views.py
  1. from . import throttlings
  2. class SendView(ViewSet):
  3.     # 发送短信频率限制
  4.     throttle_classes = [throttlings.TimeThrottling]
  5.     # 发送验证码接口
  6.     @action(methods=['GET'], detail=False)
  7.     def send(self,request,*args,**kwargs):
  8.         telephone = request.query_params.get('telephone')
  9.         if not re.match('^1[3-9][0-9]{9}$',telephone):
  10.             return APIResponse(code=0,msg='手机号不合法')
  11.         code = get_code() #获取随机验证码
  12.         result = send_message(telephone,code)
  13.         # 将验证码保存到缓存中备用,参数分别是key,value,过期时间秒
  14.         # 这个telephone可以有标识一点,在settings进行配置一下
  15.         cache.set(settings.CACHE_MSG % telephone,code,180)
  16.         # 如果result返回true
  17.         if result:
  18.             return APIResponse(msg='验证码发送成功')
  19.         else:
  20.             return APIResponse(code=0,msg='验证码发送失败')
复制代码
手机号登陆接口
serializes.py
作用:对前端发来的手机号和验证码进行校验,并签发token
  1. class UserCodeModelserialize(serializers.ModelSerializer):
  2.     code = serializers.CharField(max_length=4,min_length=4)
  3.     class Meta:
  4.         model = models.UserInfo
  5.         fields = ['telephone','code']
  6.     # 这里因为手机号验证码方式登录也需要校验和签发token,所以也需要重写validate方法
  7.     def validate(self, attrs):
  8.         user = self._get_user(attrs)
  9.         token = self._get_token(user)
  10.         self.context['user'] = user
  11.         self.context['token'] = token
  12.         return attrs
  13.     def _get_user(self, attrs):
  14.         # 获取前端发送的数据
  15.         telephone = attrs.get('telephone')
  16.         code = attrs.get('code')
  17.         # 取出生产的code与用户传的code做比较
  18.         cache_code = cache.get(settings.CACHE_MSG%telephone)
  19.         if cache_code == code:
  20.             user = models.UserInfo.objects.filter(telephone=telephone).first()
  21.             if user:
  22.                 cache.set(settings.CACHE_MSG%telephone,'')
  23.                 return user
  24.             else:
  25.                 raise ValidationError('用户不存在')
  26.         else:
  27.             raise ValidationError('验证码不正确')
  28.     # 签发token函数,前面加一个_暗示内部使用的
  29.     def _get_token(self,user):
  30.         from rest_framework_jwt.serializers import jwt_payload_handler,jwt_encode_handler
  31.         pyload = jwt_payload_handler(user) #通过user对象获取pyload
  32.         token = jwt_encode_handler(pyload) #通过pyload获取token
  33.         return token
复制代码
views.py
  1.     # 验证码方式登录接口
  2.     @action(methods=['POST'], detail=False)
  3.     def code_login(self, request, *args, **kwargs):
  4.         # 把前端传入的用户登录数据传入序列化器
  5.         ser = serializers.UserCodeModelserialize(data=request.data)
  6.         # 判读传入的数据是否合法
  7.         if ser.is_valid():
  8.             # 合法获取token和用户名
  9.             token = ser.context['token']
  10.             username = ser.context['user'].username
  11.             # 然后返回给前端
  12.             return APIResponse(token=token, username=username)
  13.         else:
  14.             return APIResponse(code='0', msg=ser.errors)
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4