permissions.py源码分析
permissions.py 源码分析
SAFE_METHODS = ('GET', 'HEAD', 'OPTIONS')
#GET请求,HEAD获取头部信息,OPTIONS获取可用请求类型设置为安全方法
#POST,PUT,PATCH,DELETE都会修改数据,没有加到这个元组
@six.add_metaclass(BasePermissionMetaclass)
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
#所有权限类都该继承它
#两个方法,has_perm,has_obj_perm
AllowAny 源码
class AllowAny(BasePermission):
"""
Allow any access.
This isn't strictly required, since you could use an empty
permission_classes list, but it's useful because it makes the intention
more explicit.
"""
def has_permission(self, request, view):
return True
#允许任何访问
#不是严格需要,因为可以使用空的权限类,但它会使代码更清晰
IsAuthenticated 源码
class IsAuthenticated(BasePermission):
"""
Allows access only to authenticated users.
"""
def has_permission(self, request, view):
return bool(request.user and request.user.is_authenticated)
#只要认证用户允许访问
#重写了has_permission方法,返回(用户为真)和(用户被认证为真)的与值
IsAdminUser 源码
class IsAdminUser(BasePermission):
"""
Allows access only to admin users.
"""
def has_permission(self, request, view):
return bool(request.user and request.user.is_staff)
#只允许管理员用户访问
#is_staff是users表里的一个字段
class IsAuthenticatedOrReadOnly(BasePermission):
"""
The request is authenticated as a user, or is a read-only request.
"""
def has_permission(self, request, view):
return bool(
request.method in SAFE_METHODS or
request.user and
request.user.is_authenticated
)
#认证用户的请求,或者只读请求
#请求方法在SAFE_METHODS 这个元组里则返回True
#请求用户为认证用户也返回True
DjangoModelPermissions 源码
class DjangoModelPermissions(BasePermission):
"""
The request is authenticated using `django.contrib.auth` permissions.
See: https://docs.djangoproject.com/en/dev/topics/auth/#permissions
It ensures that the user is authenticated, and has the appropriate
`add`/`change`/`delete` permissions on the model.
This permission can only be applied against view classes that
provide a `.queryset` attribute.
"""
# Map methods into required permission codes.
# Override this if you need to also provide 'view' permissions,
# or if you want to provide custom permission codes.
perms_map = {
'GET': [],
'OPTIONS': [],
'HEAD': [],
'POST': ['%(app_label)s.add_%(model_name)s'],
'PUT': ['%(app_label)s.change_%(model_name)s'],
'PATCH': ['%(app_label)s.change_%(model_name)s'],
'DELETE': ['%(app_label)s.delete_%(model_name)s'],
}
authenticated_users_only = True
def get_required_permissions(self, method, model_cls):
"""
Given a model and an HTTP method, return the list of permission
codes that the user is required to have.
"""
kwargs = {
'app_label': model_cls._meta.app_label,
'model_name': model_cls._meta.model_name
}
if method not in self.perms_map:
raise exceptions.MethodNotAllowed(method)
return [perm % kwargs for perm in self.perms_map[method]]
def _queryset(self, view):
assert hasattr(view, 'get_queryset') \
or getattr(view, 'queryset', None) is not None, (
'Cannot apply {} on a view that does not set '
'`.queryset` or have a `.get_queryset()` method.'
).format(self.__class__.__name__)
if hasattr(view, 'get_queryset'):
queryset = view.get_queryset()
assert queryset is not None, (
'{}.get_queryset() returned None'.format(view.__class__.__name__)
)
return queryset
return view.queryset
def has_permission(self, request, view):
# Workaround to ensure DjangoModelPermissions are not applied
# to the root view when using DefaultRouter.
if getattr(view, '_ignore_model_permissions', False):
return True
if not request.user or (
not request.user.is_authenticated and self.authenticated_users_only):
return False
queryset = self._queryset(view)
perms = self.get_required_permissions(request.method, queryset.model)
return request.user.has_perms(perms)
#使用django.contrib.auth权限认证请求
#确保用户被认证,并且在model上拥有合适的add,change,delete的权限
#只有在有queryset属性的类视图上使用
#
#perms_map
#映射方法到权限码
#如果要提供view权限,或者自定义权限码,重写它
#每个method对应一个列表,格式是app_label.codename,比如cmdb.add_gameid
#
#get_required_permissions
#输入一个model和http方法
#如果method没有在perms_map映射表,则抛出错误
#返回权限列表
#
#_queryset
#检查视图中有没有queryset属性或者get_queryset方法,没有则报错。
#
#has_permission
#检查有没有权限
#如果view中定义_ignore_model_permissions则直接返回True
#如果账户没有认证,则返回False
#将用户拥有的权限返回
```
```python
class DjangoModelPermissionsOrAnonReadOnly(DjangoModelPermissions):
"""
Similar to DjangoModelPermissions, except that anonymous users are
allowed read-only access.
"""
authenticated_users_only = False
#继承自DjangoModelPermissions
#改变一个参数,允许匿名用户的只读访问
全局设置
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.AllowAny',
),
#在rest_framework/settings.py中,默认的权限配置AllowAny
REST_FRAMEWORK = {
...
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.DjangoModelPermissions',
),
}
#可以在项目的settings中,修改为DjangoModelPermissions,这是最常用的
局部设置
只允许认证用户访问,只对这个viewset生效
from rest_framework.permissions import IsAuthenticated
class SvrconfigViewSet(viewsets.ReadOnlyModelViewSet):
"""
retrieve:
返回指定信息
list:
返回列表
"""
queryset = Svrconfig.objects.all()
serializer_class = SvrconfigSerializer
permission_classes = (IsAuthenticated,)
#给一个视图集设置权限,只有认证用户可以访问
#没有用户信息,会出现401错误
get权限
在DjangoModelPermissions中,默认get是不需要权限的,但业务中的查看一般是需要权限的所以需要重写。
project/permissions.py
#重建权限映射
from rest_framework.permissions import DjangoModelPermissions
class Permissions(DjangoModelPermissions):
perms_map = {
'GET': ['%(app_label)s.view_%(model_name)s'],
'OPTIONS': [],
'HEAD': [],
'POST': ['%(app_label)s.add_%(model_name)s'],
'PUT': ['%(app_label)s.change_%(model_name)s'],
'PATCH': ['%(app_label)s.change_%(model_name)s'],
'DELETE': ['%(app_label)s.delete_%(model_name)s'],
}
settings.py
REST_FRAMEWORK = {
...
'DEFAULT_PERMISSION_CLASSES': (
'project.permissions.Permissions',
),
}
Last updated