登录注册接口搭建

yizhihongxing

登录接口分析

登录分为多方式登录和验证码登录方式

多方式登录

1)前台提供账号密码,账号可能是 用户名、手机号、邮箱等

接口:
后台只需要提供一个多方式登录接口即可 - 多方式登录接口

多方式登录接口

前端输入完账号和密码,点击登录,向后端发送请求进行校验用户登录数据

urls.py

from django.urls import path,re_path,include
from rest_framework.routers import SimpleRouter
from user import views

router = SimpleRouter()
router.register('',views.LoginView,'login')

urlpatterns = [
    path('',include(router.urls)),
]

views.py

from rest_framework.viewsets import ViewSet
from user import serializers
from luffyapi.utils.response import APIResponse
from rest_framework.decorators import action
class LoginView(ViewSet):
    # 密码方式登录接口
    @action(methods=['POST'],detail=False) # 加入action装饰器,自动生成路由
    def login(self,request,*args,**kwargs):
        # 把前端传入的用户登录数据传入序列化器
        ser = serializers.UserModelserialize(data=request.data)
        # 判读传入的数据是否合法
        if ser.is_valid():
            # 合法获取token和用户名
            token =ser.context['token']
            username = ser.context['user'].username
            # 然后返回给前端
            return APIResponse(token=token,username=username)
        else:
            return APIResponse(code='0',msg=ser.errors)

serializes.py

from rest_framework import serializers
from user import models
from rest_framework.exceptions import ValidationError


class UserModelserialize(serializers.ModelSerializer):
    username = serializers.CharField() # ?
    class Meta:
        model = models.UserInfo
        fields = ['username','password','id']
        extra_kwargs = {
            'id':{'read_only':True},
            'password': {'write_only': True},
        }

    def validate(self, attrs):
        # 多种方式登录
        user = self._get_user(attrs)
        # 签发token
        token = self._get_token(user)
        # 放到context中,我在视图函数中可以取出来
        self.context['token'] = token
        self.context['user'] = user
        return attrs

    # 校验前端发来的数据
    def _get_user(self, attrs):
        # 获取前端发送的数据
        username = attrs.get('username')
        password = attrs.get('password')
        import re
        # 校验前端的用户是否为手机号、邮箱、用户名登录
        if re.match('^1[3-9][0-9]{9}$',username):
            user = models.UserInfo.objects.filter(telephone=username).first()
        elif re.match('^.+@.+$',username):
            user = models.UserInfo.objects.filter(email=username).first()
        else:
            user = models.UserInfo.objects.filter(username=username).first()
        # 用户名存在,则校验密码
        if user:
            ret = user.check_password(password)
            if ret:
                return user
            else:
                raise ValidationError('密码错误')
        else:
            raise ValidationError('用户名不存在')

    # 签发token函数,前面加一个_暗示内部使用的
    def _get_token(self,user):
        from rest_framework_jwt.serializers import jwt_payload_handler,jwt_encode_handler
        pyload = jwt_payload_handler(user) #通过user对象获取pyload
        token = jwt_encode_handler(pyload) #通过pyload获取token
        return token

验证码登录

验证码可以保存在redis里,也可以保存在缓存里

1)前台提供手机号和验证码完成登录

接口:
前台填完手机号,往后台发送校验手机号的请求,如果存在继续,不存在提示注册 - 手机号存在与否接口
前台点击发送验证码,将手机再次发送给后台,后台将手机号通知给第三方,发送短信 - 手机验证码接口
前台点击登录提交手机号与验证码,完成验证码登录 - 验证码登录接口

手机号是否存在的接口设计

    # 校验手机号是否存在接口
    @action(methods=['GET'], detail=False)
    def check_telephone(self, request, *args, **kwargs):
        telephone = request.GET.get('telephone')
        if not re.match('^1[3-9][0-9]{9}$',telephone):
            return APIResponse(code=0,msg='手机号不合法')
        try:
            models.UserInfo.objects.get(telephone=telephone)
            return APIResponse()
        except:
            return APIResponse(code=0,msg='手机号不存在')

发送验证码接口

from luffyapi.libs.tx_msg import get_code,send_message # 导入封装好的短信接口
from django.core.cache import cache # 导入缓存
from django.conf import settings
    # 发送验证码接口
    @action(methods=['GET'], detail=False)
    def send(self,request,*args,**kwargs):
        telephone = request.GET.get('telephone')
        if not re.match('^1[3-9][0-9]{9}$',telephone):
            return APIResponse(code=0,msg='手机号不合法')
        code = get_code() #获取随机验证码
        result = send_message(telephone,code)
        # 将验证码保存到缓存中备用,参数分别是key,value,过期时间秒
        # 这个telephone可以有标识一点,在settings进行配置一下
        cache.set(settings.CACHE_MSG % telephone,code,180)
        # 如果result返回true
        if result:
            return APIResponse(msg='验证码发送成功')
        else:
            return APIResponse(code=0,msg='验证码发送失败')

短信发送频率限制

写一个throttlings.py

from rest_framework.throttling import BaseThrottle, SimpleRateThrottle

# 写一个类继承SimpleRateThrottle
class TimeThrottling(SimpleRateThrottle):
    scope = 'sms'
    def get_cache_key(self, request, view):
        telephone = request.query_params.get('telephone')

        return self.cache_format%{'scope':'sms','ident':telephone} # 以手机号返回不太好,换一种不易重名的返回做限制

在settings里配置一下频率

REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_RATES': {
        'sms': '1/m'  # 一分钟访问1次
    }
}

views.py

from . import throttlings
class SendView(ViewSet):
    # 发送短信频率限制
    throttle_classes = [throttlings.TimeThrottling]
    # 发送验证码接口
    @action(methods=['GET'], detail=False)
    def send(self,request,*args,**kwargs):
        telephone = request.query_params.get('telephone')
        if not re.match('^1[3-9][0-9]{9}$',telephone):
            return APIResponse(code=0,msg='手机号不合法')
        code = get_code() #获取随机验证码
        result = send_message(telephone,code)
        # 将验证码保存到缓存中备用,参数分别是key,value,过期时间秒
        # 这个telephone可以有标识一点,在settings进行配置一下
        cache.set(settings.CACHE_MSG % telephone,code,180)
        # 如果result返回true
        if result:
            return APIResponse(msg='验证码发送成功')
        else:
            return APIResponse(code=0,msg='验证码发送失败')

手机号登陆接口

serializes.py
作用:对前端发来的手机号和验证码进行校验,并签发token

class UserCodeModelserialize(serializers.ModelSerializer):
    code = serializers.CharField(max_length=4,min_length=4)
    class Meta:
        model = models.UserInfo
        fields = ['telephone','code']

    # 这里因为手机号验证码方式登录也需要校验和签发token,所以也需要重写validate方法
    def validate(self, attrs):
        user = self._get_user(attrs)
        token = self._get_token(user)
        self.context['user'] = user
        self.context['token'] = token
        return attrs

    def _get_user(self, attrs):
        # 获取前端发送的数据
        telephone = attrs.get('telephone')
        code = attrs.get('code')
        # 取出生产的code与用户传的code做比较
        cache_code = cache.get(settings.CACHE_MSG%telephone)
        if cache_code == code:
            user = models.UserInfo.objects.filter(telephone=telephone).first()
            if user:
                cache.set(settings.CACHE_MSG%telephone,'')
                return user
            else:
                raise ValidationError('用户不存在')
        else:
            raise ValidationError('验证码不正确')


    # 签发token函数,前面加一个_暗示内部使用的
    def _get_token(self,user):
        from rest_framework_jwt.serializers import jwt_payload_handler,jwt_encode_handler
        pyload = jwt_payload_handler(user) #通过user对象获取pyload
        token = jwt_encode_handler(pyload) #通过pyload获取token
        return token

views.py

    # 验证码方式登录接口
    @action(methods=['POST'], detail=False)
    def code_login(self, request, *args, **kwargs):
        # 把前端传入的用户登录数据传入序列化器
        ser = serializers.UserCodeModelserialize(data=request.data)
        # 判读传入的数据是否合法
        if ser.is_valid():
            # 合法获取token和用户名
            token = ser.context['token']
            username = ser.context['user'].username
            # 然后返回给前端
            return APIResponse(token=token, username=username)
        else:
            return APIResponse(code='0', msg=ser.errors)

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:登录注册接口搭建 - Python技术站

(0)
上一篇 2023年4月2日
下一篇 2023年4月2日

相关文章

  • django中的视图层

    1.什么是视图层 简单来说,就是用来接收路由层传来的请求,从而做出相应的响应返回给浏览器 2.视图层的格式与参数说明 2.1基本格式 from django.http import HttpResponse def page_2003(request): html = ‘<h1>第一个网页</h1>’ return HttpRespo…

    Python开发 2023年4月2日
    00
  • 编程语言的介绍

    1. 什么是编程语言 编程语言,其实就是一种人和计算机进行沟通所需要的介质、工具。就像英语是中国人用来与外国人沟通的工具。 2.什么是编程 编程指的是:人类通过编程语言,把想要计算机做的事,写到文件中,编程的结果就是这一堆文件,这些文件就是程序。 3. 为什么要编程 计算机就像是奴隶,人类通过编程去奴役计算机,从而使计算机完成人类想要完成的任务,解放人的劳动…

    2023年4月2日
    00
  • 基础数据类型之集合

    1.集合的定义 在{}内用逗号分开多个元素,多个元素满足以下三个条件: 1.集合元素必须是不可变类型2.集合元素无序3.集合内元素没有重复(打印出来会自动去重) d = {} 默认是定义空字典 需要定义空集合,需要使用s = set() 2,集合的作用 (1)关系运算 # 如何取出这两个人共同的朋友呢? friend1=[‘zhang’,’yang’,’li…

    Python开发 2023年4月2日
    00
  • celery的介绍和使用

    celery介绍 celery是一个异步任务框架,它可以执行异步任务、延迟任务、定时任务 异步任务框架简述: 1)celery可以不依赖任何服务器,通过自身命令,启动服务(内部支持socket) 2)celery服务为为其他项目服务提供异步解决任务需求的 注:会有两个服务同时运行,一个是项目服务,一个是celery服务,项目服务将需要异步处理的任务交给cel…

    2023年4月2日
    00
  • 文章详情页制作

    url的设计 /usrname/article/1 /用户名/article/文章主键值 re_path(r’^(?P<username>\w+)/article/(?P<article_id>\d+)/$’,views.article_detail,name=’detail’), 视图函数的设计 # 七、文章详情页 def arti…

    Python开发 2023年4月2日
    00
  • 线程

    1. 什么是线程 线程就是进程里面的执行单位,每一个进程肯定都自带一个线程,真正被cpu执行的是线程,线程是代码的执行过程,该过程中需要的资源都找对应的进程要 进程是资源的单位,线程是执行单位! 补充:同一个进程里面的多个线程资源是共享的! 2. 为啥要有线程 一个进程里面可以开设多个线程,而开设线程是不需要申请内存空间的(进程需要),因此,开设线程的消耗远…

    2023年4月2日
    00
  • 序列化组件

    序列化组件的三大功能 序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串 反序列化,把客户端发送过来的数据,经过request以后变成字典,序列化器可以把字典转成模型 反序列化时同时会完成数据校验功能 序列化器Serializer使用方法 查询单个数据语法: 1.在setting.py中的app配置里注册一下drf 2.在dj…

    2023年4月2日
    00
  • 基础数据类型之元组

    1.元组的定义 元组,其实就是一个不可变的‘列表’ 用小括号()定义,括号内用逗号分隔开任意类型的数据,当只有一个数据时也需要加逗号 元组中的数据是不可改变指的是:数据的内存地址不可改变,如果元组里是列表(可变类型),可以通过方法往列表里增删值!!! 2.元组的作用 按照索引/位置存放多个数据,这些数据只用于读,不用于改 3.类型转换 tuple()方法转换…

    Python开发 2023年4月2日
    00
合作推广
合作推广
分享本页
返回顶部