博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
chapter 7 JWT 用户登录
阅读量:2344 次
发布时间:2019-05-10

本文共 7081 字,大约阅读时间需要 23 分钟。

7.1

1、urls.py设置

from rest_framework.authtoken import viewsurlpatterns = [        path('api-token-auth/', views.obtain_auth_token),]

2、sittings.py

REST_FRAMEWORK = {    'DEFAULT_AUTHENTICATION_CLASSES': (        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',        'rest_framework.authentication.BasicAuthentication',        'rest_framework.authentication.SessionAuthentication',    )}
INSTALLED_APPS = (    ...    'rest_framework.authtoken')

3、进行数据迁移

4、跟踪网页请求前端调试工具:postman

Chrome 插件postman下载安装

使用方法: 点击postman Chrome app

点击以下图标打开 postman app

填写post内容,拿到token

拿到token后将token填写到headers中

填写时注意空格

将post改为get 再发送一次,查看后台user数据

7.2 优化JWT

1、设置手机,用户名均可以登陆

user.views.py

from django.contrib.auth.backends import ModelBackendfrom django.contrib.auth import get_user_modelfrom django.db.models import QUser = get_user_model()class CustomBackend(ModelBackend):    """    自定义用户验证规则    """    def authenticate(self, username=None, password=None, **kwargs):        try:            # 不希望用户存在两个,get只能有一个。两个是get失败的一种原因            # 后期可以添加邮箱验证            user = User.objects.get(                Q(username=username) | Q(mobile=username))            # django的后台中密码加密:所以不能password==password            # UserProfile继承的AbstractUser中有def check_password(self,            # raw_password):            if user.check_password(password):                return user        except Exception as e:            return None

sittings.py

# 设置邮箱和用户名和手机号均可登录AUTHENTICATION_BACKENDS = (    'users.views.CustomBackend',)

2、设置JWT的过期时间

# 与drf的jwt相关的设置JWT_AUTH = {    'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=36000),#设置JWT过期时间    'JWT_AUTH_HEADER_PREFIX': 'Bearer',}

7.7配置云片短信发送托管网站

7.8 完成断行发送接口

1、sitting.py设置     

REGEX_MOBILE = "^1[358]\d{9}$|^147\d{8}$|^176\d{8}$"

将APIKEY的值添加到sitting.py中(APIKEY的值在云片网的用户首页获得)

# 云片网设置APIKEY = 'apikey值'

     2、在users文件夹下添加serializers.py文件

seralizers.py

import refrom datetime import datetime, timedeltafrom MxShop.settings import REGEX_MOBILEfrom users.models import VerifyCodefrom rest_framework import serializersfrom django.contrib.auth import get_user_modelUser = get_user_model()class SmsSerializer(serializers.Serializer):    mobile = serializers.CharField(max_length=11)    def validate_mobile(self, mobile):        """        验证手机号码(函数名称必须为validate_ + 字段名)        """        # 手机是否注册        if User.objects.filter(mobile=mobile).count():            raise serializers.ValidationError("用户已经存在")        # 验证手机号码是否合法        if not re.match(REGEX_MOBILE, mobile):            raise serializers.ValidationError("手机号码非法")        # 验证码发送频率        one_mintes_ago = datetime.now() - timedelta(hours=0, minutes=1, seconds=0)        # 添加时间大于一分钟以前。也就是距离现在还不足一分钟        if VerifyCode.objects.filter(add_time__gt=one_mintes_ago, mobile=mobile).count():            raise serializers.ValidationError("距离上一次发送未超过60s")        return mobile

3、   users.views.py

class SmsCodeView(CreateModelMixin,viewsets):    serializer_class = SmsSerializer    def generate_code(self):        """        生成四位数字的验证码字符串        """        seeds = "1234567890"        random_str = []        for i in range(4):            random_str.append(choice(seeds))        return "".join(random_str)    def create(self, request, *args, **kwargs):        serializer = self.get_serializer(data=request.data)        serializer.is_valid(raise_exception=True)#如果serializer没有值的话,那么直接抛出异常        mobile = serializer.validated_data["mobile"]        yun_pian = YunPian(APIKEY)        code = self.generate_code()        sms_status = yun_pian.send_sms(code=code, mobile=mobile)        if sms_status["code"] != 0:            return Response({                "mobile": sms_status["msg"]            }, status=status.HTTP_400_BAD_REQUEST)        else:            code_record = VerifyCodede(code=code, mobile=mobile)            code_record.save()            return Response({                "mobile": mobile            }, status=status.HTTP_201_CREATED)

上述的create方法是重载的

create方法源码:

def create(self, request, *args, **kwargs):        serializer = self.get_serializer(data=request.data)        serializer.is_valid(raise_exception=True)        self.perform_create(serializer)        headers = self.get_success_headers(serializer.data)        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

4、配置urls中的路由

路由名:codes

7.10用户注册

Django 信号量 装饰器

users.serializers.py 注意源码里面的一些小bug,mobile和username的混乱使用导致验证的失败,现在已经修改了

class UserRegSerializer(serializers.ModelSerializer):    code = serializers.CharField(required=True, write_only=True, max_length=4, min_length=4, label="验证码",                                 error_messages={                                     "blank": "请输入验证码",                                     "required": "请输入验证码",                                     "max_length": "验证码格式错误",                                     "min_length": "验证码格式错误"                                 },                                 help_text="验证码")    username = serializers.CharField(label="用户名", help_text="用户名", required=True, allow_blank=False,                                     validators=[UniqueValidator(queryset=User.objects.all(), message="用户已经存在")])    #将密码设置为密文 write_only将返回到前端设置为false,这样前端就会将密码隐藏    password = serializers.CharField(        style={'input_type': 'password'}, help_text="密码", label="密码", write_only=True,    )    # 调用父类的create方法,该方法会返回当前model的实例化对象即user。    # 将密码加密保存到数据库    def create(self, validated_data):        user = super(UserRegSerializer, self).create(validated_data=validated_data)        user.set_password(validated_data["password"])        user.save()        return user    def validate_code(self, code):        # get与filter的区别: get有两种异常,一个是有多个,一个是一个都没有。        # try:        #     verify_records = VerifyCode.objects.get(mobile=self.initial_data["username"], code=code)        # except VerifyCode.DoesNotExist as e:        #     pass        # except VerifyCode.MultipleObjectsReturned as e:        #     pass        # 验证码在数据库中是否存在,用户从前端post过来的值都会放入initial_data里面,排序(最新一条)。        verify_records = VerifyCodede.objects.filter(mobile=self.initial_data["mobile"]).order_by("-add_time")        if verify_records:            # 获取到最新一条            last_record = verify_records[0]            # 有效期为五分钟。            five_mintes_ago = datetime.now() - timedelta(hours=0, minutes=30, seconds=0)            if five_mintes_ago > last_record.add_time:                raise serializers.ValidationError("验证码过期")            if last_record.code != code:                raise serializers.ValidationError("验证码错误")        else:            raise serializers.ValidationError("验证码错误")    # 不加字段名的验证器作用于所有字段之上。attrs是字段 validate之后返回的总的dict,验证完code后将数据库中的code删除掉,但是这段代码似乎没有生效    def validate(self, attrs):        attrs["mobile"] = attrs["mobile"]        del attrs["code"]        return attrs    class Meta:        model = User        fields = ("username", "code", "mobile", "password")

users.views.py

class UserViewSet(CreateModelMixin,viewsets.GenericViewSet):    serializer_class = UserRegSerializer    queryset = User.objects.all()

urls.py中路由配置为users(其实我想配成register的但是怕前端出事)

Django信号量机制:没有写,觉得暂时用不到

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的文章
过来人对程序员学习Java的10条建议,第2点很重要!
查看>>
大学生如何学好Java?过来人给你7点建议
查看>>
过来人的经验:Java实习生在公司里一般都做什么?
查看>>
Java入门基础知识点整理大放送,推荐收藏
查看>>
如何成为月入25k的高级程序员?建议养成这7个习惯
查看>>
学 Java还是Python, 哪个更好找工作?
查看>>
Java基础知识:如何计算Java对象占用内存大小?
查看>>
一份Java程序员的珍藏书单,请您注意查收
查看>>
全宇宙上最全Java基础知识点归纳(建议收藏)
查看>>
这6类人,最适合做程序员!
查看>>
Java入门基础知识点需要学什么?
查看>>
为什么现在Java程序员要求高?看完这些原因你就明白了!
查看>>
有哪些值得推荐的 Java 练手项目?
查看>>
一文看清:Java的核心技术是什么?
查看>>
这10款适合Java开发人员使用的工具,你都掌握了吗?
查看>>
谈谈:如何由浅入深的学习一门编程语言?
查看>>
讨论:程序员薪资凭啥那么高?
查看>>
都2021年了,现在转行搞JAVA还来的及么?
查看>>
为什么这么多人Java基础薄弱?该如何提升?
查看>>
如何成为一名合格的Java程序员?
查看>>