• 认证组件


    简单实例

    settings.py

    INSTALLED_APPS = [
        'rest_framework',
    ]
    

    urls.py

    urlpatterns = [
        path('admin/', admin.site.urls),
        path('api/v1/auth/',views.AuthView.as_view()),
    ]
    

    models.py

    from django.db import models
    
    class UserInfo(models.Model):
        USER_TYPE = (
            (1,'普通用户'),
            (2,'VIP'),
            (3,'SVIP')
        )
    
        user_type = models.IntegerField(choices=USER_TYPE)
        username = models.CharField(max_length=32)
        password = models.CharField(max_length=64)
    
    class UserToken(models.Model):
        user = models.OneToOneField(UserInfo,on_delete=models.CASCADE)
        token = models.CharField(max_length=64)
    

    views.py

    from django.shortcuts import render,HttpResponse
    from django.http import JsonResponse
    from rest_framework.views import APIView
    from API import models
    from rest_framework.request import Request
    from rest_framework import exceptions
    from rest_framework.authentication import BasicAuthentication
    
    ORDER_DICT = {
        1:{
            'name':'apple',
            'price':15
        },
        2:{
            'name':'dog',
            'price':100
        }
    }
    
    def md5(user):
        import hashlib
        import time
        #当前时间,相当于生成一个随机的字符串
        ctime = str(time.time())
        m = hashlib.md5(bytes(user,encoding='utf-8'))
        m.update(bytes(ctime,encoding='utf-8'))
        return m.hexdigest()
    
    class AuthView(object):
        '''用于用户登录验证'''
        def post(self,request,*args,**kwargs):
            ret = {'code':1000,'msg':None}
            try:
                user = request._request.POST.get('username')
                pwd = request._request.POST.get('password')
                obj = models.UserInfo.objects.filter(username=user,password=pwd).first()
                if not obj:
                    ret['code'] = 1001
                    ret['msg'] = '用户名或密码错误'
                #为用户创建token
                token = md5(user)
                #存在就更新,不存在就创建
                models.UserToken.objects.update_or_create(user=obj,defaults={'token':token})
                ret['token'] = token
            except Exception as e:
                ret['code'] = 1002
                ret['msg'] = '请求异常'
            return JsonResponse(ret)
    
    
    class Authentication(APIView):
        '''认证'''
        def authenticate(self,request):
            token = request._request.GET.get('token')
            token_obj = models.UserToken.objects.filter(token=token).first()
            if not token_obj:
                raise exceptions.AuthenticationFailed('用户认证失败')
            #在rest framework内部会将这两个字段赋值给request,以供后续操作使用
            return (token_obj.user,token_obj)
    
        def authenticate_header(self, request):
            pass
    
    class OrderView(APIView):
        '''订单相关业务'''
    
        authentication_classes = [Authentication,]    #添加认证
        def get(self,request,*args,**kwargs):
            #request.user
            #request.auth
            ret = {'code':1000,'msg':None,'data':None}
            try:
                ret['data'] = ORDER_DICT
            except Exception as e:
                pass
            return JsonResponse(ret)

    总结:

    	-写一个认证类(继承BaseAuthentication)
    		-重写authenticate方法,把request对象传入
    		-能从request对象中取出用户携带的token,根据token判断是否登录过
    		-如果登录过,返回两个值 user对象,token对象
    		-如果没有登录过抛异常
    	-全局使用
    		-在settings中配置
    			REST_FRAMEWORK={
                    "DEFAULT_AUTHENTICATION_CLASSES":["app01.service.auth.Authentication",]
                    }
    	-局部使用
    		-在视图类中配置:
    			authentication_classes=[Authentication,]
    	-局部禁用:
    		-在视图类中配置:
    			authentication_classes=[]
    

      

    认证源码分析

    -APIView中的dispatch  --->  self.initial(认证,频率,权限) --->   self.perform_authentication(认证)  --->   本质又调用了新的request对象的user方法
      -->  request.user内部执行了:self._authenticate(注意self是新的request对象)  --->   循环拿到一个个认证类的对象,执行对象的authenticate方法,传入request对象
    --->   一个个认证类的对象是在reuqest对象实例化的时候传入的   --->   APIView中的get_authenticators,通过列表推导式生成一个个的认证类对象,然后传入request对象中

  • 相关阅读:
    第三次作业
    第二次作业
    第一次作业 2017.09.15
    WIN10共享
    当人类什么时候明白两点一线不是最近的距离的时候就是深入太空的时候
    世界的秘密:人族
    世界组成:世界如何演变
    用上了360免费云盘
    世界真相(内容偕为虚构,不用当真)
    找到一个新的超好用的U盘启动制作工具了
  • 原文地址:https://www.cnblogs.com/penghengshan/p/11134196.html
Copyright © 2020-2023  润新知