Как крупные сайты получают разрешения на уровне строк? - PullRequest
8 голосов
/ 11 января 2011

Итак, я создаю небольшой сайт с использованием cakephp, и мой ACL настроен таким образом, чтобы каждый раз при создании части контента создавалось правило ACL, связывающее владельца части контента с фактическим контентом.Это позволяет каждому владельцу редактировать / удалять свой собственный контент.Этот метод кажется просто неэффективным, потому что в базе данных есть эквивалентное количество правил ACL.Мне было любопытно, как большие сайты с миллионами контента решают эту проблему?

Ответы [ 3 ]

10 голосов
/ 11 января 2011

С большими сайтами у меня работали, права доступа определялись на уровне приложения. База данных связала контент с записью пользователя, после чего на уровне доступа к данным / бизнес-логики было принято решение, достаточно ли у пользователя прав для доступа к контенту.

Для большого сайта с динамическим контентом я думаю, что это, вероятно, лучший способ справиться с этим.

РЕДАКТИРОВАТЬ: Чтобы добавить более конкретный пример.

Пример: Хорошо, допустим, у нас есть простой сайт для хранения файлов, где пользователь может получить доступ только к своим данным или данным, которые были явно переданы им другим пользователем.

Поскольку это приложение довольно простое, поскольку оно просто обслуживает файлы, оно имеет только три таблицы базы данных:

Users Table which has columns:
      UserId <int>  PK
      UserName <varchar>
      HashedPassword <varchar>
Files Table which has columns:
      FileId <int>  PK
      FileOwnerId <int> FK (this has a foreign key relationship with UserId in the users table)
      FileName <varchar>
      MimeType <varchar>
      FileData <blob>
SharedFile reference table which has columns:
      SharedFileIndex <int> PK
      FileId <int> FK
      UserId <int> FK

Теперь некоторые основные правила, которые мы захотим определить на нашем уровне доступа к данным, заключаются в том, что, когда пользователь вошел в систему, он может получить доступ к файлам, владельцем которых он является, и к файлам, которыми другие пользователи поделились с ним. Таким образом, либо с помощью хранимых процедур, либо создав запрос для отправки на сервер базы данных, я бы удостоверился, что мои запросы возвращают только те записи, к которым у них есть доступ.

Вот базовый SQL-запрос GetUsersFileList, когда пользователь входит в систему:

SELECT FileId, FileName, FileType
FROM Files
WHERE FileOwnerId = @UserId

Как вы можете видеть здесь, мы используем параметризованный запрос для получения файлов, владельцем которых является пользователь. Кроме того, мы будем запрашивать общие файлы, а также отображать их для пользователя.

Теперь, если мы предположим, что у каждого файла будет свой уникальный URL, например:

http://mydomain.com/filehandler.php?fileId=123546

Затем, когда мы пытаемся получить файл, мы используем запрос, аналогичный приведенному выше, чтобы попытаться получить данные файла:

SELECT FileName, FileType, FileData
FROM Files
LEFT OUTER JOIN SharedFiles on Files.FileId = SharedFiles.FileId
WHERE Files.FileId = @FileId AND (FileOwnerId = @UserId OR SharedFiles.UserId = @UserId)

Итак, вы видите, что когда мы пытаемся получить файл, мы все еще используем UserId в запросе, таким образом, если у пользователя нет файла, к которому он был предоставлен, или он не является владельцем файла, результат запроса будет быть 0 строк.

Таким образом, разрешения определяются тем, что пользователь отображает в базе данных, но фактическое применение осуществляется путем тщательного написания вашего кода доступа к данным и / или дополнительных проверок на уровне бизнес-логики перед подачей контента.

EDIT2: я больше всего знаком с MSSQL, поэтому мои запросы выше относятся к T-SQL, поэтому синтаксис для MySql может быть немного невелик.

EDIT3: заменен уровень бизнес-логики уровнем доступа к данным, поскольку в этом примере выполняются только проверки внутри самих запросов доступа к данным.

EDIT4: Хорошо, вернемся к уровню бизнес-логики, поскольку более сложным приложениям потребуются более сложные схемы разрешений, что может потребовать дополнительных проверок на уровне бизнес-логики.

2 голосов
/ 11 января 2011

Вместо того, чтобы иметь отдельный ACL для каждого элемента контента, вы можете иметь отдельный ACL для каждого различного набора разрешений.Большинство элементов содержимого для данного пользователя будут иметь одинаковые разрешения, поэтому все они могут указывать на один и тот же ACL.Это также может позволить вам кэшировать проверки разрешений (например, «пользователь 123 имеет разрешение на чтение ACL 456»).В итоге у вас будет очень мало ACL - только все стандартные и несколько исключений.

0 голосов
/ 11 января 2011

Одно и то же правило применяется как к большим, так и к маленьким сайтам - если вам нужен более конкретный контроль, вам нужно хранить больше данных в базе данных. Проблема, которую вы пытаетесь решить [позволить пользователям управлять только своим контентом], может быть решена с помощью простой ссылки на идентификатор пользователя между таблицами [например, users.id <-> article.userId], нет необходимости связывать каждую строку с пользователем. Я бы предложил использовать более общие правила и хранить только исключения [например, позволяющие указанным пользователям редактировать содержимое других пользователей] в качестве внешних данных.

...