【问题标题】:Django hook to deny user access to admin based on siteDjango 挂钩根据站点拒绝用户访问管理员
【发布时间】:2015-01-14 02:29:33
【问题描述】:

我们有一个 Django 项目,其中包含多个站点(使用 Sites 框架的派生),其中每个站点都是我们域的子域。我需要能够根据用户是否具有站点的外键来拒绝某些员工用户(具有站点外键的自定义用户模型的实例)访问管理站点。

自定义用户模型基本上是这样的:

class SiteTenantUser(AbstractUser):
    site = models.ForeignKey(Site, null=True)

您的第一个倾向可能是建议我们使用自定义SiteAuthBackend 身份验证后端的authenticate 方法阻止身份验证,以便只让用户登录自己的站点。这可以防止身份验证,但诀窍是我们的超级用户确实具有跨站点访问权限,因此我们希望使用通配符会话 cookie (.ourdomain.com) 让超级用户无需登录即可从一个站点转到另一个站点在每一次。但是,通过这样做,我们现在需要除了 authenticate 之外的其他东西来防止没有该权限的用户进行跨站点访问。否则,他们可以针对自己的站点进行身份验证,然后切换到另一个站点的管理 url 并进行合法会话并进入大门。

总之,虽然我们的自定义身份验证后端阻止非超级用户员工用户(仅限于单个站点)登录到另一个站点的管理员,但它不会阻止他们登录到自己的管理员然后切换到另一个网站的管理员。是否有一个简单的钩子来防止这种情况,类似于 Django 如何从任何管理页面拒绝没有is_staff 的用户,无论他们是否经过身份验证?

PS 我们有一个全局的 get_current_site 方法,它使用来自中间件的缓存值,可以在任何地方工作,不需要请求。

【问题讨论】:

    标签: python django django-admin


    【解决方案1】:

    您可以创建自定义中间件来拒绝用户访问。在AuthenticationMiddleware之后添加到MIDDLEWARE_CLASSES

    from django.http import HttpResponseForbidden 
    
    class CheckUserSiteMiddleware(object):
    
        def process_request(self, request):
            if (request.path.startswith('/admin/') and
                    request.user.is_authenticated() and
                    user.site != get_current_site()):
                return HttpResponseForbidden()
    

    【讨论】:

      【解决方案2】:

      我最终创建了一个自定义 AdminSite,如下所示:

      from django.contrib.admin import AdminSite
      
      class TenantSitesAdminSite(AdminSite):
          def has_permission(self, request):
              user = request.user
              return (
                  user.is_active and
                  user.is_staff and
                  (user.is_superuser or user.site == get_current_site()))
      
      site = TenantSitesAdminSite()
      

      为了使我的自定义site 生效,我必须将contrib.admin.site 的所有用法切换为使用自定义site,以及从contrib.admin.site 注销任何第三方或贡献管理员并重新注册使用自定义site 注册它们,或者(邪恶的)猴子补丁contrib.admin.site 以指向自定义site。我不会承认我所做的。 :)

      通过使用 CustomAdminSite 并重新定义 has_permission 逻辑,在特定站点上没有权限的员工用户在尝试访问管理员时获得与非员工用户相同的体验 - 这将被带到管理员登录页面。 @catvaran 的建议奏效了,但用户只会得到 403 错误页面,如果不返回他们被授权并注销的站点,甚至无法进入管理员登录页面,我更希望体验相同至于编外用户(即对未经授权的管理页面的任何请求都会将它们带到管理员登录页面)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-22
        • 2018-03-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多