Django REST框架允许只有超级用户才能访问API Web视图。

8

我正在使用 Django 2.0Django RESET Framework 来编写我的应用程序的 REST API

我已经配置了以下身份验证方法:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ),
}

目前,所有经过身份验证的用户都可以访问web api视图。

我想要的是允许少数用户(可能是超级管理员用户)通过会话认证或通过登录到Web浏览器来访问API。

编辑2:contacts/views.py

class ContactViewSet(viewsets.ModelViewSet):
    queryset = Contact.objects.all()
    serializer_class = ContactSerializer
    permission_classes = (IsAuthenticated,)

    def perform_create(self, serializer):
        serializer.save(user_id=self.request.user)

你能添加你的联系人API视图吗? - rtindru
问题中的代码已更新。 - Anuj TBE
你确定浏览器请求是使用经过身份验证的用户吗? - rtindru
我知道了,我的配置有一点问题。但是如何将Web访问限制为仅超级管理员用户? - Anuj TBE
你需要创建一个自定义中间件或将其集成到视图中。没有任何理由根据用户访问系统的方式来限制其使用同样的功能。 - Roger Collins
你可以在这里做些很酷的事情;请给我一分钟 - rtindru
3个回答

14

适用于Django 2(在views.py中添加)

from rest_framework.permissions import IsAdminUser

class IsSuperUser(IsAdminUser):
    def has_permission(self, request, view):
        return bool(request.user and request.user.is_superuser)

class ListSmth(ListCreateAPIView):
    permission_classes = (IsSuperUser,)
    ... Your code...

1
最好从rest_framework.permissions.BasePermission继承,而不是从rest_framework.permissions.IsAdminUser继承。 - Mukesh Sai Kumar

5

已经有一个名为IsAdminUser的内置类,将其指定为permission_classes属性的值即可。

from rest_framework.permissions import  IsAdminUser
     class A:
       permission_classes = (IsAdminUser,)

这个检查数值是否存在

reques.user.isStaff == True

请注意(如您所说),这里检查的是is_staff,但问题指定的是超级用户。 - undefined

3

因此,您可以利用 permission_classes 来实现这一点。DRF 的 Request 对象在一个名为 _authenticator 的属性中记住了使用的身份验证方法。您可以利用这个属性,并使用 permission_classes 来确定 (user, authenticator) 这一对是否有权限。

class AdminAuthenticationPermission(permissions.BasePermission):
    ADMIN_ONLY_AUTH_CLASSES = [rest_framework.authentication.BasicAuthentication, rest_framework.authentication.SessionAuthentication]

    def has_permission(self, request, view):
        user = request.user
        if user and user.is_authenticated():
            return user.is_superuser or \
                not any(isinstance(request._authenticator, x) for x in self.ADMIN_ONLY_AUTH_CLASSES) 
        return False

class ContactViewSet(viewsets.ModelViewSet):
    queryset = Contact.objects.all()
    serializer_class = ContactSerializer
    permission_classes = (IsAuthenticated, AdminAuthenticationPermission,)

未经测试:但应该可以工作


1
太好了,它正在工作。只需要进行一点修改。从 is_authenticated() 中删除 ()。其他都很好。 - Anuj TBE
太好了!我想这是Django 1.10的变化;我更习惯于1.9 老习惯 https://docs.djangoproject.com/en/2.0/releases/1.10/#using-user-is-authenticated-and-user-is-anonymous-as-methods - rtindru
1
是的,我之前在1.10版本中使用了同样的东西。但在2.0版本中会返回“TypeError: 'bool' object is not callable”。 - Anuj TBE
我建议您更新您的问题,以反映实际的根本问题和相应的答案,以便更好地参考未来。 - rtindru
移除 user.is_authenticated() 末尾的 () 可以修复 TypeError @AnujTBE。 - Mojtaba Arvin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接