欢迎来到Louis的博客

人生三从境界:昨夜西风凋碧树,独上高楼,望尽天涯路。 衣带渐宽终不悔,为伊消得人憔悴。 众里寻他千百度,蓦然回首,那人却在灯火阑珊处。
扩大
缩小

05-权限

添加权限

1.在utils/文件夹下新建permission.py文件

  • message是当没有权限时,提示的信息
class SVIPPermission(object):
    message = '你的权限不够,'

    def has_permission(self, request, view):
        if request.user.user_level != 3:
            return False
        else:
            return True

 

2.settings.py全局配置

REST_FRAMEWORK = {
    "DEFAULT_PERMISSION_CLASSES": ['utils.permission.SVIPPermission']
}

 

(3) views.py添加认证

  • 默认是所有页面都需要SVIP权限才能访问
  • Login类不需要认证,不用配置
from django.shortcuts import render
from django.contrib.auth import authenticate

from rest_framework.views import APIView
from rest_framework.response import Response

from .models import UserInfo, UserToken
from utils.get_token import generate_token
from utils.throttle import VisitThrottle


class Login(APIView):
    # 认证
    authentication_classes = []
    # 节流
    throttle_classes = [VisitThrottle]
    # 权限
    permission_classes = []  # 为空表示不校验权限

    def post(self, request):
        # 响应的字典
        response = dict()
        fields = {'username', 'password'}
        user_info = dict()
        if fields.issubset(set(request.data)):
            for key in fields:
                user_info[key] = request.data[key]

        # 使用Django认证组件进行校验
        user_instance = authenticate(**user_info)

        # 校验成功
        if user_instance is not None:
            # 生成token
            access_token = generate_token()
            # 更新或创建Token
            UserToken.objects.update_or_create(user=user_instance, defaults={'token': access_token})
            response['status_code'] = 200
            response['status_message'] = '登录成功'
            response['access_token'] = access_token
            response['user_role'] = user_instance.get_user_level_display()
        else:
            # 校验失败
            response['status_code'] = 201
            response['status_message'] = '用户名或密码错误'

        return Response(response)
from utils.auth_component import UserAuth


class BookView(ModelViewSet):
    authentication_classes = [UserAuth]
    # permission_classes = [UserPermission]
    # 登录用户节流
    throttle_classes = [UserThrottle]
    queryset = Book.objects.all()
    serializer_class = BookSerialize
urlpatterns = [
    path('login/', views.Login.as_view()),
    path('reg/',views.Reg.as_view()),
]
from django.urls import path, re_path
from app01.views import (ApiViews,
                         MixinViews,
                         GenericsViews,
                         ModelViewSet)

urlpatterns = [
    # APIView
    path('book1/', ApiViews.BookView.as_view()),
    re_path('book1/(\d+)/$', ApiViews.BookFilterView.as_view()),

    # MixinViews
    path('book2/', MixinViews.BookView.as_view()),
    re_path('book2/(?P<pk>\d+)/$', MixinViews.BookFilterView.as_view()),

    # GenericViews
    path('book3/', GenericsViews.BookView.as_view()),
    re_path(r'book3/(?P<pk>\d+)/$', GenericsViews.BookFilterView.as_view()),

    # ModelViewSet
    path('book4/', ModelViewSet.BookView.as_view({
        'get': 'list',
        'post': 'create'
    })),
    re_path(r'book4/(?P<pk>\d+)/$', ModelViewSet.BookView.as_view({
        'get': 'retrieve',
        'put': 'update',
        'delete': 'destroy'
    }))
]

(4). 测试

用户登录,正常访问

用户level

dangshuai的user_level是1,尝试访问/book4/,权限校验失败

用wanghua的token访问,权限校验成功

 

权限源码流程

 (1)dispatch

 
    def dispatch(self, request, *args, **kwargs):
        """
        `.dispatch()` is pretty much the same as Django's regular dispatch,
        but with extra hooks for startup, finalize, and exception handling.
        """
        self.args = args
        self.kwargs = kwargs
        #对原始request进行加工,丰富了一些功能
        #Request(
        #     request,
        #     parsers=self.get_parsers(),
        #     authenticators=self.get_authenticators(),
        #     negotiator=self.get_content_negotiator(),
        #     parser_context=parser_context
        # )
        #request(原始request,[BasicAuthentications对象,])
        #获取原生request,request._request
        #获取认证类的对象,request.authticators
        #1.封装request
        request = self.initialize_request(request, *args, **kwargs)
        self.request = request
        self.headers = self.default_response_headers  # deprecate?

        try:
            #2.认证
            self.initial(request, *args, **kwargs)

            # Get the appropriate handler method
            if request.method.lower() in self.http_method_names:
                handler = getattr(self, request.method.lower(),
                                  self.http_method_not_allowed)
            else:
                handler = self.http_method_not_allowed

            response = handler(request, *args, **kwargs)

        except Exception as exc:
            response = self.handle_exception(exc)

        self.response = self.finalize_response(request, response, *args, **kwargs)
        return self.response
 

(2)initial

 
    def initial(self, request, *args, **kwargs):
        """
        Runs anything that needs to occur prior to calling the method handler.
        """
        self.format_kwarg = self.get_format_suffix(**kwargs)

        # Perform content negotiation and store the accepted info on the request
        neg = self.perform_content_negotiation(request)
        request.accepted_renderer, request.accepted_media_type = neg

        # Determine the API version, if versioning is in use.
        version, scheme = self.determine_version(request, *args, **kwargs)
        request.version, request.versioning_scheme = version, scheme

        # Ensure that the incoming request is permitted
        #4.实现认证
        self.perform_authentication(request)
        #5.权限判断
        self.check_permissions(request)
        self.check_throttles(request)
 

(3)check_permissions

里面有个has_permission这个就是我们自己写的权限判断

 
    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)
                )
 

(4)get_permissions

 def get_permissions(self):
        """
        Instantiates and returns the list of permissions that this view requires.
        """
        return [permission() for permission in self.permission_classes]

(5)permission_classes

 

 所以settings全局配置就如下

#全局
REST_FRAMEWORK = {
   "DEFAULT_PERMISSION_CLASSES":['API.utils.permission.SVIPPremission'],
}

 

内置权限

 django-rest-framework内置权限BasePermission

默认是没有限制权限

 
class BasePermission(object):
    """
    A base class from which all permission classes should inherit.
    """

    def has_permission(self, request, view):
        """
        Return `True` if permission is granted, `False` otherwise.
        """
        return True

    def has_object_permission(self, request, view, obj):
        """
        Return `True` if permission is granted, `False` otherwise.
        """
        return True
 

 

我们自己写的权限类,应该去继承BasePermission,修改之前写的permission.py文件

 
# utils/permission.py

from rest_framework.permissions import BasePermission

class SVIPPremission(BasePermission):
    message = "必须是SVIP才能访问"
    def has_permission(self,request,view):
        if request.user.user_type != 3:
            return False
        return True
 

 

总结:

(1)使用

  • 自己写的权限类:1.必须继承BasePermission类;  2.必须实现:has_permission方法

(2)返回值

  • True   有权访问
  • False  无权访问

(3)局部

  • permission_classes = [MyPremission,] 

 (4)全局

REST_FRAMEWORK = {
   #权限
    "DEFAULT_PERMISSION_CLASSES":['utils.permission.SVIPPremission'],
}

 

 

 

posted on 2018-12-11 19:29  Louiszj  阅读(157)  评论(0)    收藏  举报

导航