Как обеспечить разделение на основе аккаунта в Django
У меня есть приложение Django, в котором используется модель с одним аккаунтом. Мы конвертируем это в мульти-аккаунт, поэтому почти каждая модель будет иметь ForeignKey(Account)
,
Какой самый простой способ убедиться, что каждый Account
(каждая учетная запись находится в своем собственном поддомене) может получить доступ только к своим собственным данным? У нас есть промежуточное ПО, которое заполняет поддомен и текущую учетную запись по каждому запросу.
Мы можем сделать это трудным путем, добавив filter(...., account = request.account)
во всех наших взглядах. Это не желательно, как,
filter(...., account = request.account)
будет добавлен ко всем запросам, что делает его не сухим, повторяющимся и подверженным ошибкам.- Большим риском является отсутствие фильтра, где бы это ни было, это риск для безопасности.
5 ответов
Я не думаю, что есть какой-то явный победитель, особенно если учесть, что не все запросы нужно будет фильтровать по аккаунту. Также рассмотрим старый threadlocals
хитрость считается ненадежной, что означает, что единственный способ сделать автоматическую вставку параметров фильтра был бы с промежуточным программным обеспечением, я думаю... но это также кажется ненадежным и сложным для меня.
Я также не нашел хорошего способа создать диспетчер запросов, который мог бы здесь помочь, но это возможно.
Итак, я думаю, что лучшее решение для "мультитенантной" базы данных - просто убедиться, что все ваши запросы отфильтрованы по аккаунту. Вы можете сделать это с:
Промежуточное программное обеспечение режима отладки, такое как Middleware: средство записи владельца
В ваших тестах проверьте sql, сгенерированный любыми тестами, и убедитесь, что поле запроса находится в запросе. Вы также можете включить в свои тестовые данные данные "другой учетной записи", чтобы ваш тест не отображался ни в одном из результатов запроса.
Убедитесь, что все запросы проверены на наличие фильтра во время проверки кода
Конечно, не красиво, но лучшее, что я смог сделать до сих пор.
Ух, у меня точно такая же проблема. Вот лучший ответ, который я получил:
Джанго: Как можно организовать этот большой беспорядок моделей / менеджеров / дизайнеров?
Этот фрагмент может поставить вас в правильном направлении. Я считаю, что разрешения на уровне строк тоже есть в списке задач 1.2, но не уверен на 100%.
Есть ли какая-то серьезная причина, по которой вы не можете просто написать функцию, которая автоматически вставляет учетную запись сеанса в запрос и принимает все остальные параметры в качестве аргументов?
Ты используешь django.contrib.auth
?
Если вы, просто сделайте аккаунт ForeignKey(User, unique=true)
и укажите все ваши модели на пользователя
то есть. ForeignKey(User)
Кроме того, взгляните на Django Auth Docs
редактировать: я думаю, что теперь я понимаю вашу озабоченность немного лучше...
Вместо того чтобы делать
my_model.objects.filter(user=request.user)
просто делать:
request.user.my_model_set.all()