zoukankan      html  css  js  c++  java
  • Django-restframework 源码之认证组件源码分析

    Django-restframework 源码之认证组件源码分析

    一 前言

    之前在 Django-restframework 的流程分析博客中,把最重要的关于认证、权限和频率的方法找到了。该方法是 APIView 的一个名为initial的类方法,也就是在 views 中定义的视图类方法,继承自APIView方法。该方法源码如下:

    那么当代码执行到这里时,最开始执行的是用户的认证,也就是perform_autnentication方法。下面来深入的分析一下在用户认证中具体是怎么执行的。

    二 用户认证执行流程

    进入查看该方法源码如下:

    1. 执行APIView.perform_authentication

    2. 执行 Request.user

    3. 执行Request._authenticate

    4. Request.authenticators

    5. APIView.initialize_request

    6. APIView.get_authticators

    7. api_settings.DEFAULT_AUTHENTICATION_CLASSES

    到这里就是查找APIView 配置的问题了,后面的DEFAULT_AUTHENTICATION_CLASSES是默认的认证类,该类定义在settings.py文件中。之后我会写一篇 Django 加载项目配置的博客,到时候详细分析一下,这会涉及到 python 的两种加载文件的方式,一种是 import;一种是使用importlib模块导入。

    三 自定义认证组件

    了解了 restframework 的认证流程,对于需要自定义认证组件其实很明了,就是自定义认证类,重写 authenticate 方法。不过这还不行,我们还需要进行一下配置。

    需求:在之前的项目中,我们需要在服务器中保存相关的 cookie 或 session 来进行用户身份校验,那么如何使用 restframework 的认证来实现该需求,使得既能校验身份,也可以不用在服务端保存用户的 cookie 或 session。

    首先不管 cookie 或 session 都是为了校验用户的,那么在这里我们可以使用一个随机字符串(加密后的),当客户端朝服务端发送请求时会携带该值,之后进行反解用来对比。

    1. urls.py

    url(r'^login/', views.Login.as_view()),
    

    2. Views.py

    # 获取 随机token值
    def get_token(id, salt='123'):
        md = hashlib.md5()
        md.update(bytes(str(id), encoding='utf-8'))
        md.update(bytes(salt, encoding='utf-8'))
    
        return md.hexdigest() + '|' + str(id)
    
    # 登陆视图类
    class Login(APIView):
    
        # def dispatch(self, request, *args, **kwargs):
        #     return super(Login, self).dispatch(request, *args, **kwargs)
    
        def post(self, request):
            response = {'status': 100, 'msg': None}
            name = request.data.get('name')
            password = request.data.get('password')
            print(name, password)
            user_obj = models.UserInfo.objects.filter(name=name, password=password).first()
            if user_obj:
                token = get_token(user_obj.pk)
                response['msg'] = '登陆成功'
                response['status'] = 100
                response['token'] = token
                print('111', token)
            else:
                response['msg'] = '用户名或密码错误'
            return Response(response)
        
    

    3. authenticate_classes.py

    # 校验 token
    def check_token(token, salt='123'):
        ls = token.split('|')
        md = hashlib.md5()
        md.update(bytes(ls[-1], encoding='utf-8'))
        md.update(bytes(salt, encoding='utf-8'))
        if md.hexdigest() == ls[0]:
            return True
        else:
            return False
    
    
    # 改写的认证类
    class BookAuth(BaseAuthentication):
    
        def authenticate(self, request):
            token = request.data.get('token')
            print('222', token)
            if token:
                succ = check_token(token)
                if succ:
                    print('333')
                    # user =
                    return
                else:
                    raise NotAuthenticated('认证失败')
            else:
                raise NotAuthenticated('请先登录')
    

    四 配置自定义认证类

    1. 局部配置

    假设一个功能需要登陆成功才可以使用,那么只需要在该视图类中定义一个参数authentication_classes

    class Book(APIView):
        # 配置该参数可以局部使用
        authentication_classes = [authticate_classes.BookAuth, ]
    
        def dispatch(self, request, *args, **kwargs):
            return super().dispatch(request, *args, **kwargs)
    
        def get(self, request, id):
            print(request.user, '444')
            response = {'status': 100, 'msg': None}
            book_obj = models.Book.objects.filter(pk=id).first()
            if book_obj:
                book_ser = myser.BookSer(book_obj, many=False)
                response['book'] = book_ser.data
            else:
                response['msg'] = '图书没有对象'
                response['status'] = 101
            return Response(response)
    

    2. 全局使用

    全局使用的话需要在项目 settings 中配置,如下:

    REST_FRAMEWORK={
        "DEFAULT_AUTHENTICATION_CLASSES":["app01.authenticate_classes.BookAuth",]
    }
    

    这样对 views 中所有的请求方法都有效。因为所有的视图类都会加载 settings 中的配置。这些都是在dispatch方法中完成的。

    3. 局部禁用

    局部禁用的话只需要在视图类中定义一个空的authentication_classes

    authentication_classes = []
    
  • 相关阅读:
    A Node Influence Based Label Propagation Algorithm for Community detection in networks 文章算法实现的疑问
    Fast Newman-FN算法以及模块度定义介绍
    Label Propagation Algorithm LPA 标签传播算法解析及matlab代码实现
    设计一个smartnic
    Intel GEN11 GPU
    Intel GEN9 GPU
    Shared Virtual Memory (SVM) Functions
    connect via ssh to virtualbox guest vm without knowing ip address
    smartnic
    技术精品翻译
  • 原文地址:https://www.cnblogs.com/zuanzuan/p/10433109.html
Copyright © 2011-2022 走看看