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'],
}
浙公网安备 33010602011771号