代码之家  ›  专栏  ›  技术社区  ›  westmark

如何在“站点”框架支持的多个Django站点中获得独特的用户?

  •  23
  • westmark  · 技术社区  · 16 年前

    我正在构建一个Django站点框架,它将为几个独立的站点提供动力,所有这些站点都使用相同的应用程序,但有自己的模板。我计划通过使用多个设置文件并为它们设置一个唯一的站点ID来实现这一点,就像Django文档中为 django.contrib.sites framework

    但是,我不希望来自站点A的用户能够登录站点B。在检查了syncdb创建的用户表之后,我看不到可能限制用户访问特定站点的列。我还尝试在一个站点上创建一个用户“bob”,然后使用shell命令列出另一个站点上的所有用户,当然,bob会出现在那里。

    如何确保所有用户都被限制在各自的网站上?

    3 回复  |  直到 13 年前
        1
  •  25
  •   Carl Meyer    13 年前

    最兼容的方法是创建一个 user Profile model 其中包括站点模型的外键,然后编写 custom auth backend 它检查当前站点与该fk的值。一些示例代码:

    定义您的配置文件模型,比如在app/model s.py中:

    from django.db import models
    from django.contrib.sites.models import Site
    from django.contrib.auth.models import User
    
    class UserProfile(models.Model):
        user = models.OneToOneField(User)
        site = models.ForeignKey(Site)
    

    编写自定义的auth后端,从默认后端继承,比如在app/auth_backend.py中:

    from django.contrib.auth.backends import ModelBackend
    from django.contrib.sites.models import Site
    
    class SiteBackend(ModelBackend):
        def authenticate(self, **credentials):
            user_or_none = super(SiteBackend, self).authenticate(**credentials)
            if user_or_none and user_or_none.userprofile.site != Site.objects.get_current():
                user_or_none = None
            return user_or_none
    
        def get_user(self, user_id):
            try:
                return User.objects.get(
                    pk=user_id, userprofile__site=Site.objects.get_current())
            except User.DoesNotExist:
                return None
    

    这个认证后端假定所有用户都有一个配置文件;您需要确保您的用户创建/注册过程始终创建一个配置文件。

    被重写的 authenticate 方法确保用户只能登录正确的站点。这个 get_user 方法是根据用户会话中存储的身份验证信息从数据库中提取用户的每个请求调用的;我们的重写确保用户不能登录站点A,然后使用同一会话cookie获得对站点B的未经授权的访问权(感谢Jan Wrobel指出需要处理后一种情况)。

        2
  •  2
  •   kripto_ash    16 年前

    您可以在考虑站点ID的情况下插入自己的授权和身份验证后端。

    参见 other authentication sources 关于Django文档和 authentication backends references

    此外,如果您的django源太旧,您可以自己修改authenticate()或login()代码。毕竟…这不是开源的奇迹之一吗?请注意,这样做可能会影响与其他模块的兼容性。

    希望这有帮助。

        3
  •  -1
  •   bluszcz    16 年前

    你必须知道,很多人抱怨Django默认授权系统和特权——它只是对对象的规则,对对象的实例——这意味着,如果不编写任何代码,就不可能实现。

    但是,有一些授权挂钩可以帮助您实现此目标,例如:

    看看那里: http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/models.py 为了班级许可。

    您可以添加自己的权限并为其定义规则(用户和ContentType有一个ForeignKey)。

    但是,如果没有MonkeyPatching/改变某些方法,可能会很困难。

    推荐文章