【问题标题】:DRF Model permissions fail for LDAP auth'd usersLDAP 身份验证用户的 DRF 模型权限失败
【发布时间】:2018-07-27 01:44:06
【问题描述】:

我正在开发一个基于 DRF 的应用程序,需要 LDAP 身份验证。我遇到了一个问题,我看到直接通过 DRF API 登录的用户和从外部应用程序(即 Curl/Postman)访问它的用户的不同行为。

在应用程序中,一旦登录,我会提供一系列用户可以访问的视图/url,即下面的 url 以查看“示例”:

http://:8000/api/samples

我已使用自定义权限类将 DjangoModelPermissions 应用到我的示例视图,该视图需要模型权限才能查看模型,即:

class HasModelPermission(permissions.DjangoModelPermissions):
    perms_map = {
        'GET': ['%(app_label)s.read_%(model_name)s'],
        'OPTIONS': ['%(app_label)s.read_%(model_name)s'],
        'HEAD': ['%(app_label)s.read_%(model_name)s'],
        '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'],
    }

class SampleView(generics.ListAPIView):
    queryset = Sample.objects.all()
    serializer_class = SampleSerializer
    permission_classes = [HasModelPermission]

根据https://django-auth-ldap.readthedocs.io/en/latest/permissions.html#group-mirroring,我已经使用 AUTH_LDAP_FIND_GROUP_PERMS=true 配置了我的 ldap 设置,并为我关心的 LDAP 组创建了匹配的 DJANGO 组 - 我已经为这些组分配了模型权限。这正如我所期望的那样工作 - 只有拥有查看列表权限的组成员的用户才能看到它。

我看到的关键问题是,虽然内部 DRF API 正确确定用户权限,但外部登录然后提交 GET 请求的用户被确定没有查看权限。

我通过一些调试确定原因是 django_auth_ldap.backend.py 中的以下代码中的测试失败,该代码从 DRF 中的视图调度程序调用,本质上,当我访问 url 时从内置的 DRF API 中,“hasattr(user, 'ldap_user'):”返回 true,当我通过邮递员或 curl 等连接时,“hasattr(user,'ldap_user'):”返回 false - 显然意味着没有用户权限确定存在。

def get_group_permissions(self, user, obj=None):
    if not hasattr(user, 'ldap_user') and self.settings.AUTHORIZE_ALL_USERS:
        _LDAPUser(self, user=user)  # This sets user.ldap_user

    if hasattr(user, 'ldap_user'):
        permissions = user.ldap_user.get_group_permissions()
    else:
        permissions = set()

    return permissions

所以我想最终我的问题是,我应该如何在来自远程端点的 HTTP 操作之间填充/维护 user.ldap_user 属性。 (注意我使用的是会话和令牌认证 ATM)。我猜我的问题更多与在操作之间维护用户 lda_user 属性数据有关,或者能够在每个连续操作中检索它。

【问题讨论】:

    标签: python django django-rest-framework django-auth-ldap


    【解决方案1】:

    我遇到了同样的错误,并用 django_auth_ldap LDAPackend 修复了它。

    我也有自己的Token模型;这是简短的版本:

    from django_auth_ldap.backend import LDAPBackend
    from rest_framework import authentication
    from users.models import Token
    
    class TokenAuthentication(authentication.TokenAuthentication):
        def authenticate_credentials(self, key):
            token = Token.objects.prefetch_related('user').get(key=key)
           
            ldap_backend = LDAPBackend()
            user = ldap_backend.populate_user(token.user.username)
            if user:
                return user, token
    
            return token.user, token
    

    【讨论】:

      【解决方案2】:

      通过设置AUTH_LDAP_AUTHORIZE_ALL_USERS = True,您将验证所有请求(包括 curl/postman 请求)。

      如果您只希望它用于您的令牌身份验证端点(开销低于 populate_user()),您可以选择:

      class TokenAuthentication(TokenAuthentication):
          def authenticate(self, request):
              # authenticate user
              user, token = super().authenticate(request)
      
              # set user.ldap_user
              _LDAPUser(LDAPBackend(), user=user)
      
              # or:
              # user = LDAPBackend().get_user(user.id)
      
             return user, token
      

      与缓存一起使用很有用:AUTH_LDAP_CACHE_TIMEOUT

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-20
        • 2020-04-14
        • 2015-04-19
        • 2016-02-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多