【问题标题】:Best way to extend django authentication/authorization扩展 django 身份验证/授权的最佳方式
【发布时间】:2012-08-29 13:15:41
【问题描述】:

我正在向我们的网站添加服务条款接受要求,并试图找出在 Django's authentication 框架内处理此问题的最佳方法。

为简单起见,这里有一个UserProfile 模型:

class UserProfile(models.Model):
    user = models.OneToOneField(User)
    accepted_tos_at = models.DateTimeField(default=None, editable=False, null=True)

所以基本上我想要做的是检查accepted_tos_at 不是None(或者实际上大于最后一次 TOS 修订的日期)。如果它通过了这个测试,那么我们可以正常验证,但如果它是None,除了logintos_display 之外的所有视图都无法访问。

我不知道你应该如何在全球范围内进行这项工作?我不想在我的每一个视图中添加user_passes_test 装饰器,同样我想避免在我的每一个视图中测试这个权限。必须有更清洁的方法。

【问题讨论】:

    标签: django authentication


    【解决方案1】:

    一般来说,当您谈论应该适用于每个视图的东西时,您就是在谈论中间件。在你的情况下,这是相对简单的:

    class AcceptTOSMiddleware(object):
        def process_request(request):
            login_url = reverse('login')
            tos_url = reverse('tos_display')
            if request.path not in [login_url, tos_url]:
                profile = request.user.get_profile()
                if profile.accepted_tos_at is None or \
                   profile.accepted_tos_at < settings.LAST_TOS_REVISION:
                    return HttpResponseRedirect(tos_url)
            return None
    

    首先,这会检查请求的 URL 是否不是登录或 TOS 视图。如果需要重定向,这可以防止无限循环。然后,您检查accepted_tos_at。我假设您只是将上次修订日期存储为设置,因此如果您有其他计划,则需要对其进行修改。如果需要接受 TOS,则将用户重定向到 TOS 视图,否则,中间件返回None,告诉 Django 继续正常处理请求。

    只需将中间件添加到 MIDDLEWARE_CLASSES 即可。

    【讨论】:

      【解决方案2】:

      我最近使用基于类的视图和 mixin 完成了身份验证。以django-braces 中的LoginRequiredMixin 为例。

      这确实意味着您的所有视图(您想要保护的)都需要包含一个通用的 mixin,但这是我所知道的最简洁的方法。

      用法(来自docs)是这样的:

      from django.views.generic import TemplateView
      from braces.views import LoginRequiredMixin
      
      
      class SomeSecretView(LoginRequiredMixin, TemplateView):
          template_name = "path/to/template.html"
      
          def get(self, request):
              return self.render_to_response({})
      

      您可能想要定义自己的 mixin,它可能看起来像这样(未经测试):

      class AcceptedTOSRequiredMixin(object):
          def dispatch(self, request, *args, **kwargs):
              profile = request.user.get_profile()
      
              if not profile or profile.accepted_tos_at is None:
                  return HttpResponseForbidden()  # return a forbidden response.
      
              return super(AcceptedTOSRequiredMixin, self).dispatch(request,
                           *args, **kwargs)
      

      其他方法涉及在 URL 级别装饰它们,但在我看来,这更丑陋(如果有帮助,我很乐意挖掘它的外观示例)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-13
        • 2011-04-09
        • 2014-11-13
        • 2012-05-20
        • 1970-01-01
        • 1970-01-01
        • 2017-07-21
        • 2011-09-27
        相关资源
        最近更新 更多