• Django REST Framework的认证方式及自定义认证


    一、基于Token进行用户认证

    创建相应数据库

    class member_type(models.Model):
        mtype = models.CharField(max_length=50)
        def __unicode__(self):
            return self.mtype
    
    class member(models.Model):
        username = models.CharField(max_length=30)
        password = models.CharField(max_length=100)
        email = models.EmailField()
        user_type = models.ForeignKey("member_type")
        def __unicode__(self):
            return self.username
    
    class member_token(models.Model):
        user = models.OneToOneField(to=member)
        token = models.CharField(max_length=64)
        def __unicode__(self):
            return self.token
    

        

    配置路由

    from abyss import views
    from django.conf.urls import url
    
    urlpatterns = [
        url(r'^api/v1/auth$', views.AuthView.as_view(),name='auth'),
        url(r'^api/v1/order$', views.OrderView.as_view(),name='order'),
    ]
    

    在setting文件中,添加rest framework应用

    INSTALLED_APPS = [
        'rest_framework',
    ]
    

    配置视图认证

    from rest_framework.views import APIView
    from rest_framework.authentication import BaseAuthentication
    from rest_framework import exceptions
    from django.http import JsonResponse
    from django.shortcuts import HttpResponse
    import hashlib
    import time
    
    class Myauthentication(BaseAuthentication):
        '''认证类'''
        def authenticate(self, request):
            token = request._request.GET.get("token")
            token_obj = models.member_token.objects.filter(token=token).first()
            if not token_obj:
                raise exceptions.AuthenticationFailed('用户认证失败')
            return (token_obj.user, token_obj)  # 这里返回值一次给request.user,request.auth
    
        def authenticate_header(self, request):
            pass
    
    def make_token(user):
        ctime = str(time.time())
        hash=hashlib.md5(user.encode("utf-8"))
        hash.update(ctime.encode("utf-8"))
        return hash.hexdigest()
    
    class AuthView(APIView):
        """登录认证"""
        def dispatch(self, request, *args, **kwargs):
            return super(AuthView,self).dispatch(request,*args, **kwargs)
        def get(self,request, *args, **kwargs):
            return HttpResponse('get is ok')
        def post(self,request, *args, **kwargs):
            ret={'code':1000,'msg':"登录成功",'token':None}
            try:
                user = request._request.POST.get("username")
                pwd = request._request.POST.get("password")
                obj = models.member.objects.filter(username=user,password=pwd).first()
                if not obj:
                    ret['code'] = 1001
                    ret['msg'] = "用户名或密码错误"
                else:
                    token = make_token(user)
                    models.member_token.objects.update_or_create(user=obj,defaults={"token":token})
                    ret['token'] = token
            except exceptions as e:
                ret['code'] = 1002
                ret['msg'] = "请求异常"
    
            return JsonResponse(ret)
    
    class OrderView(APIView):
        """查看订单信息"""
    
        authentication_classes = [Myauthentication,]  #添加认证
        def get(self, request, *args, **kwargs):
            # request.user
            # request.auth
            ret = {'code': 1003, 'msg': "你的订单已经完成", 'data': "买了一个媳妇"}
            return JsonResponse(ret, safe=True)
    

    登录认证,登录后会生成token值

    使用token进行订单查询:

    二、全局自定义认证

    通过对Django rest framework认证的源码分析知道,可以直接在项目的settings.py配置文件中引入自定义的认证类,即可以对所有的url进行用户认证流程

    在应用app目录下创建utils包,在utils包下创建auth.py文件,内容为自定义的认证类

    from rest_framework.authentication import BaseAuthentication
    from rest_framework import exceptions
    from abyss import models
    
    class Myauthentication(BaseAuthentication):
        '''认证类'''
        def authenticate(self, request):
            token = request._request.GET.get("token")
            token_obj = models.member_token.objects.filter(token=token).first()
            if not token_obj:
                raise exceptions.AuthenticationFailed('用户认证失败')
    
            # restframework会将元组赋值给request,以供后面使用
            return (token_obj.user, token_obj)  # 这里返回值一次给request.user,request.auth
    
        def authenticate_header(self, request):
            pass
    

     settings.py中的REST_FRAMEWORK作为key作为配置,所以全局配置示例:

    REST_FRAMEWORK = {
        'DEFAULT_AUTHENTICATION_CLASSES':['abyss.utils.auth.Myauthentication',]
    }
    

    #其中写认证的类的路径,不要在views中,这里我放在了utils目录下auth.py中

    此外,因为开启了全局认证,所以每个接口视图中:authentication_classes = [Myauthentication,] 就不需要设置了。

    局部某个视图不需要认证情况,如认证AuthView应该是可以直接访问的,那就如下设置:

    authentication_classes = []    #authentication_classes为空,代表不需要认证
    

    三、配置匿名用户

    匿名用户配置

    REST_FRAMEWORK = {
        "DEFAULT_AUTHENTICATION_CLASSES":['API.utils.auth.Authentication',],  
        #其中写认证的类的路径,不要在views中,这里我放在了utils目录下auth.py中
        "UNAUTHENTICATED_USER": lambda:"匿名",
        #匿名用户配置,只需要函数或类的对应的返回值,对应request.user="匿名"
        "UNAUTHENTICATED_token": None,
        #匿名token,只需要函数或类的对应的返回值,对应request.auth=None
    
    }
    

    四、Django rest framework内置的认证类

    1.BaseAuthentication

    BaseAuthentication是django rest framework为我们提供了最基本的认证类,正如源码流程一样,该类中其中定义的两个方法authenticate和authenticate_header(认证失败返回的响应头),使用时候重写该两个方法进行认证,正如示例:

    class BaseAuthentication(object):
        """
        All authentication classes should extend BaseAuthentication.
        """
    
        def authenticate(self, request):
            """
            Authenticate the request and return a two-tuple of (user, token).
            """
            raise NotImplementedError(".authenticate() must be overridden.")
    
        def authenticate_header(self, request):
            """
            Return a string to be used as the value of the `WWW-Authenticate`
            header in a `401 Unauthenticated` response, or `None` if the
            authentication scheme should return `403 Permission Denied` responses.
            """
            pass
    

     其它认证类:

    ##路径:rest_framework.authentication
    
    BasicAuthentication  #基于浏览器进行认证,浏览器弹框
    SessionAuthentication #基于django的session进行认证
    RemoteUserAuthentication #基于django admin中的用户进行认证,这也是官网的示例
    TokenAuthentication #基于drf内部的token认证

     五、总结

    1.自定义认证类:

    继承BaseAuthentication,重写authenticate方法和authenticate_header(pass就可以),authenticate()方法需要有三种情况(返回元祖、出现异常、返回none)。

    2.认证配置:

    #全局认证
    REST_FRAMEWORK = {
        "DEFAULT_AUTHENTICATION_CLASSES":['API.utils.auth.Authentication',]
    }
    
    #局部认证
    authentication_classes = [BaseAuthentication,]
    
    #是某个视图不进行认证
    authentication_classes =[]
    
  • 相关阅读:
    html常用属性手记
    html常用标签手记
    linux安装与命令大全
    14.ref参数
    13.out参数
    10.结构
    9.枚举
    8.常量
    6.使用Convert进行类型转换
    5.C#中的转义符和@符号
  • 原文地址:https://www.cnblogs.com/honey-badger/p/9740207.html
Copyright © 2020-2023  润新知