本篇详细介绍如何使用Django REST Framework自带的权限类,如何自定义权限类及如何配置权限类实现对用户访问文章资源进行控制。以及使用默认的基于session机制的用户认证。在下一篇中将重点介绍DRF的认证机制,并把重点放在Token认证和jwt认证上。
前面使用DRF开发了博客文章列表资源和单篇文章资源这两个API,支持客户端以各种请求方式对文章资源进行增删查改。目前的API 对谁可以新建、编辑或删除文章资源(Article)没有限制,本篇将通过认证(Authentication)与权限(Permission)来实现一些更实用的功能:
- 只有经过身份验证的用户可以创建article文章(匿名用户不允许通过POST提交新文章)。
- 未经身份验证的请求应具有完全只读访问权限。
- 单篇article资源始终与创建者相关联,只有article的创建者可以更新或删除它。
前面文章参考:
1、Django开发总结:Django MVT与MVC设计模式,请求过程与代码示例(附源码)_SteveRocket的博客-CSDN博客
2、DRF实战总结:基于函数的视图API以及自定义序列化器(附源码)_SteveRocket的博客-CSDN博客
认证(Authentication)与权限(Permission)的区别
认证(Authentication)与权限(Permission)不是一回事。
认证(Identification): 根据声明者持有的特定信息(用户提供的用户ID/密码组合或者Token),来确认声明者的身份(验证用户身份)。
- 例如身份证、用户名/密码、手机(包括短信、二维码、手势密码)、电子邮箱、生物特征(虹膜、面部、指纹、语音等)。
- 高安全要求的场景下,会使用多种认证方式组合进行身份校验,即多因素认证。
授权(Authorization): 资源所有者委派执行者,赋予其指定范围的权限,执行对资源的操作
- 授权实体例如银行卡、门禁卡、钥匙、证书等。
- 例如web服务的session机制、浏览器的cookie机制、授权令牌token等。
- 权限(Permission)的校验发生在验证用户身份以后,是由系统根据分配权限确定用户可以访问何种资源以及对这种资源进行何种操作,这个过程也被称为授权(Authorization)。
鉴权(Authentication): 对一个声明者的身份权利的真实性进行鉴别
- 授权和鉴权是一个一一对应的流程,有授权才会去鉴权。
权限控制(Access/Permission Control): 将可执行的操作定义为权限列表,然后判断操作是允许/禁止。
- 权限是将操作人的行为抽象化的一个概念。
无论是Django还是DRF, 当用户成功通过身份验证以后,系统会把已通过验证的用户对象与request请求绑定,这样就可以使用request.user获取这个用户对象的所有信息了。
这几个概念之间的关系:认证 -> 授权 -> 鉴权 -> 权限控制。一般情况下认证/授权同时发生,认证即授权,然后在后续行为中进行鉴权和权限控制
认证和鉴权的异同
- 认证确认的是声明者的身份,鉴权则是对声明者声明的权限进行确认
- 认证需要通过声明者独特的信息进行识别,鉴权则是通过鉴别授权过程中定义的某个媒介,这个媒介具有真实有效、不可篡改、不可伪造等特性
给视图添加权限
在前面的教程中编写ArticleList和ArticleView两个基于类的视图(如下所示)。前者如果收到GET请求会返回文章资源列表,如果收到POST请求则添加文章;后者如果收到GET请求就返回单篇文章资源,如果收到PUT或DELETE请求,就对文章资源进行修改或删除。
以上两个视图其实是有很大问题的,因为任何用户包括匿名用户也可以对文章资源进行修改。比如当访问单篇文章资源时,不仅可以看到红色的delete按钮和修改文章内容的表单,而且可以在未登录的情况对它们进行操作。
【GET】http://localhost/v1/articles4/3/
在Django传统视图开发中可能会使用@login_required和@permission_required这样的装饰器要求用户先登录或进行权限验证。在DRF中不需要做,这是因为REST framework 包含许多默认权限类,可以用来限制谁可以访问给定的视图。在这种情况下,需要的是 IsAuthenticatedOrReadOnly 类,它将确保经过身份验证的请求获得读写访问权限,未经身份验证的请求将获得只读的权限。
现在修改的视图(drf_pro/views_cbv.py),添加如下代码:
此时再访问文章资源列表或单篇文章资源时,会看到红色的delete按钮和添加修改表单都已消失。
【GET】http://localhost/v1/articles_cbv3/3/
当重新登录验证身份后,又可以看到delete按钮和修改表单了,如下所示:
DRF中用户不是访问admin的 url登录验证身份,只有管理员才能通过admin页面登录。DRF中可以将登录页面api-auth添加到的项目urls中,如下所示:
#django_rest_framework_pro/urls.py
然后访问http://localhost/drf-api-auth/login/就可以看到专门的DRF的登录页面了,如下所示:
常用DRF自带权限类
除了IsAuthenticatedOrReadOnly 类,DRF自带的常用权限类还包括:
- IsAuthenticated类:仅限已经通过身份验证的用户访问;
- IsAdminUser
- AllowAny类:允许任何用户访问;
- IsAdminUser类:仅限管理员访问;
- DjangoModelPermissions类:只有在用户经过身份验证并分配了相关模型权限时,才会获得授权访问相关模型。
- DjangoModelPermissionsOrReadOnly类:与前者类似,但可以给匿名用户访问API的可读权限。
- DjangoModelPermissionsOrAnonReadOnly
- DjangoObjectPermissions类:只有在用户经过身份验证并分配了相关对象权限时,才会获得授权访问相关对象。通常与django-gaurdian联用实现对象级别的权限控制。
django-gaurdian的详细使用,参考:《二十六、Django进阶:Django权限-第三方库Django-guardian使用详解》
自定义权限类
IsAuthenticatedOrReadOnly 类并不能实现只有文章 article 的创建者才可以更新或删除它,这时还需要自定义一个名为IsOwnerOrReadOnly 的权限类,把它加入到ArticleDetail视图里。
首先在drf_pro文件夹下创建permissions.py,添加如下代码:
# drf_pro/permissions.py
然后修改视图,IsOwnerOrReadOnly 的权限类,把它加入到ArticleDetail视图的permission_classes里。这样就完美实现了文初想要实现的三个功能,同时DRF支持权限类的插拔。
#drf_pro/views.py
全局设置默认权限策略以及函数视图添加权限
在前面的案例中,都是在基于类的API视图里通过permission_classes属性设置的权限类。如果有些权限是全局或全站通用的,还可以在settings.py中使用 DEFAULT_PERMISSION_CLASSES 全局设置默认权限策略。
例如:
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
)
}
如果未指定,则此设置默认为允许无限制访问:
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.AllowAny',
)
如果习惯使用基于函数的视图编写API,可以按如下方式给的函数视图添加权限。
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
@api_view(['GET'])
@permission_classes((IsAuthenticated, ))
def example_view(request, format=None):
content = {
'status': 'request was permitted'
}
return Response(content)
注意:当通过类属性或装饰器设置新的权限类时,您会告诉视图忽略 settings.py 文件上设置的默认列表。
代码地址:https://download.csdn.net/download/zhouruifu2015/87652849
输入才有输出,吸收才能吐纳。——码字不易