DRF比Django的认证和权限高在哪里 (2)

image-20201219151728225

刚才的错误没有了,但是报了个新的错误:Snippet.owner必须是User实例,给它赋值的是AnonymousUser(匿名用户),导致ValueError了。这个报错是发生这条代码:

serializer.save(owner=self.request.user)

也就是说请求访问视图后,进行反序列化了,但是反序列化失败了。非常奇怪!我们的请求中并没有用户信息,正常来说在访问视图的时候就该被拦截了。

给视图添加认证

我们需要让API更符合常规,让未认证的用户不能执行视图中的代码。DRF提供了rest_framework .permissions来给视图添加认证:

DRF比Django的认证和权限高在哪里

其中IsAuthenticatedOrReadOnly表示只有认证了才能读写,否则只能读。把它添加到SnippetList和SnippetDetail视图中:

from rest_framework import permissions permission_classes = [permissions.IsAuthenticatedOrReadOnly]

再请求试试,刚才的错误没有了,API返回的是需要提供用户凭证:

image-20201219160601041

登录视图

如果用浏览器打开:8000/snippets/,会发现只有GET方法没有POST,这是因为需要添加DRF登录视图,在tutorial/urls.py中添加rest_framework.urls:

urlpatterns += [ path('api-auth/', include('rest_framework.urls')), ]

api-auth/可以自定义。

刷新页面右上角就会出现Log in按钮,登录后就能POST了。

对象级权限

为了更细粒度的控制权限,让用户只能编辑自己创建的snippet,新建snippets/permissions.py:

from rest_framework import permissions class IsOwnerOrReadOnly(permissions.BasePermission): """ Custom permission to only allow owners of an object to edit it. """ def has_object_permission(self, request, view, obj): # Read permissions are allowed to any request, # so we'll always allow GET, HEAD or OPTIONS requests. if request.method in permissions.SAFE_METHODS: return True # Write permissions are only allowed to the owner of the snippet. return obj.owner == request.user

新增IsOwnerOrReadOnly权限,继承了permissions.BasePermission,重写了has_object_permission()方法。接着在snippets/views.py中给SnippetDetail加上:

from snippets.permissions import IsOwnerOrReadOnly permission_classes = [permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly]

试下访问其他用户创建的snippet,发现只能查看:

image-20201219180310509

访问自己创建的snippet,可以修改和删除:

image-20201219180516850

自定义权限

以上是官网的示例,我在Postman测试了下,发现超管dongfanger可以创建snippet:

image-20201219152719121

普通用户player也可以创建snippet:

image-20201219153118906

我想让普通用户不能创建,只能超管创建。仿照官网示例,在snippets/permissions.py中添加IsAdminOrReadOnly:

class IsAdminOrReadOnly(permissions.BasePermission): def has_permission(self, request, view): return request.user.is_superuser

接着给SnippetList加上:

permission_classes = [permissions.IsAuthenticatedOrReadOnly, IsAdminOrReadOnly]

用普通用户尝试创建,提示没有权限:

image-20201219181059751

用超级管理员尝试创建,成功:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyjyjx.html