Как получить уникальных пользователей на нескольких сайтах Django, работающих на основе "сайтов"? - PullRequest
24 голосов
/ 10 сентября 2009

Я создаю инфраструктуру сайта Django, которая будет работать на нескольких независимых сайтах, причем все они будут использовать одни и те же приложения, но со своими собственными шаблонами. Я планирую сделать это, используя несколько файлов настроек и установив для них уникальный SITE_ID, как предложено в Django документах для django.contrib.sites framework

Однако я не хочу, чтобы пользователь с сайта A мог входить на сайт B. После проверки пользовательской таблицы, созданной syncdb, я не вижу столбца, который мог бы ограничить пользователя определенным сайтом. Я также пытался создать пользователя 'bob' на одном сайте, а затем с помощью команды оболочки вывести список всех пользователей с другой стороны и, конечно же, там появился bob.

Как я могу обеспечить доступ всех пользователей к своим сайтам?

Ответы [ 3 ]

25 голосов
/ 10 сентября 2009

Наиболее совместимый способ сделать это - создать модель профиля пользователя , которая включает внешний ключ к модели сайта, а затем написать настраиваемый аутентификационный бэкэнд , который проверяет текущий сайт против стоимости этого ФК. Пример кода:

Определите модель своего профиля, скажем, в app / models.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)

Напишите свой собственный аутентификационный бэкэнд, наследуя от стандартного, скажем, в 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. (Спасибо Ян Вробель за указание на необходимость обработки последнего случая.)

2 голосов
/ 10 сентября 2009

Вы можете подключить свои собственные бэкэнды авторизации и аутентификации, которые принимают во внимание идентификатор сайта.

См. другие источники аутентификации в документации django и ссылки на бэкэнды аутентификации

Кроме того, если ваш исходный код django слишком старый, вы всегда можете изменить код authenticate () или login () самостоятельно. В конце концов ... Разве это не одно из чудес открытого кода. Имейте в виду, что этим вы можете повлиять на совместимость с другими модулями.

Надеюсь, это поможет.

0 голосов
/ 10 сентября 2009

Вы должны знать, что многие люди жалуются на систему авторизации по умолчанию и привилегии Django - у нее просто правила для объектов, для экземпляров объектов - что это значит, что без написания какого-либо кода это будет невозможно. 1001 *

Однако, есть несколько хуков авторизации, которые могут помочь вам достичь этой цели, например:

Взгляните туда: http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/models.py и для разрешения класса.

Вы можете добавить свое собственное разрешение и определить правила для них (есть ForeignKey для пользователя и для ContentType).

Однако2, без обезличивания / изменения некоторых методов это может быть сложно.

...