• APIView之dispatch中认证与权限源码刨析:


    权限和认证源码解析:

    上回讲到dispatch的核心是认证与权限,现在我们来分析一下这两者之间的源码:

    self.perform_authentication(request)
    self.check_permissions(request)
    

    执行认证:

    def perform_authentication(self, request):
        """
        Perform authentication on the incoming request.
    
        Note that if you override this and simply 'pass', then authentication
        will instead be performed lazily, the first time either
        `request.user` or `request.auth` is accessed.
        """
        request.user
    
    # property可以将方法转换为属性
    @property
    def user(self):
        """
        Returns the user associated with the current request, as authenticated
        by the authentication classes provided to the request.
        """
        # 如果你没有user.
        if not hasattr(self, '_user'):
            with wrap_attributeerrors():
                self._authenticate()
        return self._user
    
    @user.setter
    def user(self, value):
        """
        Sets the user on the current request. This is necessary to maintain
        compatibility with django.contrib.auth where the user property is
        set in the login and logout functions.
    
        Note that we also set the user on Django's underlying `HttpRequest`
        instance, ensuring that it is available to any middleware in the stack.
        """
        self._user = value
        self._request.user = value
    
    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
                # 成功者!!!
                return
        # 通往成功的路只有一条,其他都是错!!
        self._not_authenticated()
    
    将所有的认证器都遍历了一遍,然后调用每个认证器的认证方法,认证成功返回一个两位的元组,如果异常或为空都是认证失败。认证成功会将结果拆包存到self上面,即request。
    class BaseAuthentication:
        """
        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
    

    创建authentications.py >

    class TokenAuthentication(BaseAuthentication):
        #  Authenticate the request and return a two-tuple of (user, token).
    	def authenticate(self, request):
        	try:
                # 查询参数:querry_params  == 以前的 "GET"
                token = request.query_params.get("token")
                # 缓存中拿token
                user_id = cache.get(token)
                user = User.objects.get(pk=user_id) 
                # 认证成功
                return user,token
            
            except Exception as e:
                print(e)
                # 认证失败
                return 
    

    view.py >

    from 0.0 import TokenAuthentication
    
    class UserView(GenericAPIView):
        # 获取结果集
        queryset = Cart.objects.all()
        # 将数据库序列化
        serializer_class = CartSerializer
        # 获取认证
        authentication_classes = TokenAuthentication,
        
        def get(self, request, *args, **kwargs):
            
            print(request.user) # 判断是不是我们库里的用户,游客用户是AnonymosUser
            
            data = {
                "msg": "登录成功",
            }
            
            return Response(data)
    

    检查权限:

    def check_permissions(self, request):
        """
        Check if the request should be permitted.
        Raises an appropriate exception if the request is not permitted.
        """
        for permission in self.get_permissions():
            if not permission.has_permission(request, self):
                self.permission_denied(
                    request,
                    message=getattr(permission, 'message', None),
                    code=getattr(permission, 'code', None)
                )
    

    如果没有权限,权限被拒绝。

    class BasePermission(metaclass=BasePermissionMetaclass):
        """
        A base class from which all permission classes should inherit.
        """
    
        def has_permission(self, request, view):
            """
            Return `True` if permission is granted, `False` otherwise.
            """
            # 如果授予权限,则返回“True”,否则返回“False”。
            return True
    
        def has_object_permission(self, request, view, obj):
            """
            Return `True` if permission is granted, `False` otherwise.
            """
            return True
    

    创建 permissions.py >

    from rest_framework.permissions import BasePermission
    from App.models import User
    class LoginPermission(BasePermission):
    
        def has_permission(self, request, view):
            # 只针对get请求
            if request.method == "GET":
            # request.user 是我们自己的User,拥有权限,其他就是没有权限
            return isinstance(request.user,User)
        return True
    

    view.py >

    class UserView(GenericAPIView):
        # 获取结果集
        queryset = Cart.objects.all()
        # 将数据库序列化
        serializer_class = CartSerializer
        # 获取认证
        authentication_classes = TokenAuthentication,
        # 获取权限
        permission_classes = LoginPermission,
        
        def get(self, request, *args, **kwargs):
            
            serializer = UserSerializser(request.user)
            
            data = {
                "msg": "登录成功",
                "data": serializer.data
            }
            
            return Response(data)
            
    
    以上就是用最少的代码来验证用户的身份。
  • 相关阅读:
    django-filter 使用Filter来筛选你的数据
    Django REST framework
    利用WSGI来部署你的网站
    [GitPython]使用python管理你的git库
    [模拟炉石](三)使用卡牌
    简单说pyglet.event
    [模拟炉石](二)下一步要解决的问题
    [模拟炉石](一)让游戏过程显示到cocos2d中
    docker系列之一:初见docker
    二分查找_递归实现_存在重复元素
  • 原文地址:https://www.cnblogs.com/lance-lzj/p/13860947.html
Copyright © 2020-2023  润新知