zoukankan      html  css  js  c++  java
  • rest_framework框架实现之(认证)

    一认证

    我们可以想想,我们要访问一个页面,需不需要对其进行认证,希望进入页面的时候看到哪些内容,一般是根据用户的不同而不同

    首先,我们先设计一个表,如何知道对方通过了验证,我们可以考虑给其加一个token,并且每个人都有不同的权限(大小)

    #models.py
    from django.db import models
    
    class UserInfo(models.Model):
        user_type_choices=(
            (1,'普通用户'),
            (2,'VIP'),
            (3,"SVIP")
        )
        user_type=models.IntegerField(choices=user_type_choices)
        username=models.CharField(max_length=32,unique=True)
        password=models.CharField(max_length=32)
    
    class UserToken(models.Model):
        user=models.OneToOneField(to='UserInfo') #默认就是UserInfo表的id
        token=models.CharField(max_length=64)

    其次,需要设计token,token一般是一长串字符串,我们可以使用md5对其进行转化

    #views.py
    def
    md5(user): import hashlib,time ctime=str(time.time()) m=hashlib.md5(bytes(user,encoding='utf-8')) #使用bytes方法直接让str变成bytes m.update(bytes(ctime,encoding='utf-8')) return m.hexdigest()

     设计验证方法

    #views.py
    from rest_framework.views import exceptions
    from api import models
    from rest_framework.authentication import BaseAuthentication
    #BaseAuthentication类强制要求重写 authenticate函数,要不然抛出异常 .authenticate() must be overridden

    class
    Auth_yanzheng(BaseAuthentication): 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

    token从哪里获得?当然是用户登录的时候

    #views.py
    from rest_framework.views import APIView
    from django.http import JsonResponse
    class AuthView(APIView): #根据用户登录,找出token,有就更新,没有就新建
    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=md5(user) models.UserToken.objects.update_or_create(user=obj,defaults={'token':token}) #注意update_or_create方法 ret['token']=token except Exception as e: print(e) ret['code']=1002 ret['msg']='请求异常' return JsonResponse(ret)

     接着我们设计一下url

    url(r'^api/v1/auth/$',views.AuthView.as_view()),

    下面通过postman来实现这一过程,能再数据库里面找到用户信息,则给用户加上一个token

    下面,我们来设计另外一个函数,用上我们的认证

    #urls.py
    url(r'^api/v1/auth/$',views.AuthView.as_view()),
    url(r'^api/v1/order/$',views.OrderView.as_view()),
    #views.py

    ORDER_DICT={
    1:{
    'name':"hehe",
    'age':18,
    'gender':'男',
    'content':"..."
    },
    2: {
    'name': "go",
    'age': 19,
    'gender': '男',
    'content': "..."
    }
    }

    class
    OrderView(APIView): authentication_classes = [Auth_yanzheng] def get(self,request,*args,**kwargs): # token=request._request.GET.get('token') # if not token: # return HttpResponse('用户未登录') ret={'code':1000,'msg':None,'data':None} try: ret['data']=ORDER_DICT #ORDER_DICT是我们给成功认证的用户看的东西 except Exception as e: pass return JsonResponse(ret)

    总结流程:(单一考虑认证)

    首先,经过urls,urls里面执行的是 as_view方法,找as_view方法,我们没写,---》找到父类APIview,APIview继承了view,view里面的as_view方法返回的是dispatch
    
    APIview里面的dispatch方法,执行initialize_request函数,它对request进行封装  authenticators=self.get_authenticators(),
    
    函数get_authenticators里面,遍历authentication_classes  ---》return [auth() for auth in self.authentication_classes]
    
    接着再全局变量里面找   authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES,没有就找到局部

    回到APIview执行initial函数--》执行 self.perform_authentication(request),函数perform_authentication返回 request.user

    request来自哪里呢,回到封装request的地方,发现request是一个类,找到它的user方法,里面执行 self._authenticate(),_authenticate里面循环类的对象,执行对象的authenticate方法
    authenticate就是我们自己写的方法

     下面看_authenticate

        def _authenticate(self):
            """
            Attempt to authenticate the request using each authentication instance
            in turn.
            """
            for authenticator in self.authenticators:
                try:
                    user_auth_tuple = authenticator.authenticate(self) #接收我们给的值
                except exceptions.APIException:
                    self._not_authenticated()
                    raise
    
                if user_auth_tuple is not None:
                    self._authenticator = authenticator
                    self.user, self.auth = user_auth_tuple  #分别赋值给user,auth
                    return
    
            self._not_authenticated()
     def _not_authenticated(self):
            """
            Set authenticator, user & authtoken representing an unauthenticated request.
    
            Defaults are None, AnonymousUser & None.
            """
            self._authenticator = None
    
            if api_settings.UNAUTHENTICATED_USER:
                self.user = api_settings.UNAUTHENTICATED_USER()  #如果经过了,什么用户都没有的情况下,返回默认值 AnonymousUser 
            else:
                self.user = None
    
            if api_settings.UNAUTHENTICATED_TOKEN:
                self.auth = api_settings.UNAUTHENTICATED_TOKEN()
            else:
                self.auth = None
    
    
  • 相关阅读:
    第十六周个人作业
    排球比赛积分程序
    本周个人总结
    本周个人总结
    排球积分规则
    我与计算机
    排球计分(实践)
    观后感
    18周 个人作业
    总结
  • 原文地址:https://www.cnblogs.com/mmyy-blog/p/11028768.html
Copyright © 2011-2022 走看看