Несколько типов разрешений (ролей) хранятся в базе данных как один десятичный - PullRequest
8 голосов
/ 13 сентября 2008

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

Каков наилучший способ обработки нескольких типов разрешений?

Это звучит как инновационный подход, поэтому вместо таблицы «многие ко многим отношениям users_to_roles» у меня несколько разрешений, определенных как один десятичный знак (я предполагаю, что это тип данных int). Это означает, что все разрешения для одного пользователя находятся в одной строке. Это, вероятно, не будет иметь смысла, пока вы не прочитаете другой вопрос и не ответите

Я не могу разобраться с этим. Может кто-нибудь объяснить, пожалуйста, процесс преобразования? Звучит «правильно», но я просто не понимаю, как я преобразую роли в десятичную, прежде чем она попадет в БД, и как она конвертируется обратно, когда выходит из БД. Я использую Java, но если вы окунетесь в это, это было бы здорово.

Вот исходный ответ на случай, если другой вопрос будет удален:

"Лично я иногда использую помеченное перечисление разрешений. Таким образом, вы можете использовать побитовые операции И, ИЛИ, НЕ и XOR над элементами перечисления.

[Flags]
public enum Permission
{
    VIEWUSERS = 1, // 2^0 // 0000 0001
    EDITUSERS = 2, // 2^1 // 0000 0010
    VIEWPRODUCTS = 4, // 2^2 // 0000 0100
    EDITPRODUCTS = 8, // 2^3 // 0000 1000
    VIEWCLIENTS = 16, // 2^4 // 0001 0000
    EDITCLIENTS = 32, // 2^5 // 0010 0000
    DELETECLIENTS = 64, // 2^6 // 0100 0000
}

Затем вы можете объединить несколько разрешений, используя побитовый оператор AND.

Например, если пользователь может просматривать и редактировать пользователей, двоичный результат операции - 0000 0011, который преобразуется в десятичное число - 3. Затем вы можете сохранить разрешение одного пользователя в одном столбце вашей базы данных (в нашем случае это будет 3).

Внутри вашего приложения вам просто нужна еще одна побитовая операция (ИЛИ), чтобы проверить, есть ли у пользователя определенное разрешение или нет. "

Ответы [ 2 ]

4 голосов
/ 13 сентября 2008

Вы используете побитовые операции. Псевдокод будет выглядеть примерно так:

bool HasPermission(User user, Permission permission) {
    return (user.Permission & permission) != 0;
}

void SetPermission(User user, Permission permission) {
    user.Permission |= permission;
}

void ClearPermission(User user, Permission permission) {
    user.Permission &= ~permission;
}

Разрешение - это тип перечисления, определенный в вашем сообщении, хотя любой тип должен быть основан на целочисленном типе. То же самое относится к полю User.Permission.

Если эти операторы (&, | = и & =) не имеют смысла для вас, тогда читайте о побитовых операциях (побитовое И и побитовое ИЛИ).

3 голосов
/ 13 сентября 2008

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

Если вы собираетесь сделать что-то подобное, вам действительно будет полезно иметь таблицу чисел . Это сделает ваши расчеты намного быстрее.

Базовая настройка включает в себя следующие таблицы:

  1. Группы - для многих пользователей и точек безопасности
  2. Точки безопасности - содержат значение для анонимной авторизации и значение для аутентифицированных пользователей, которые не входят в отдельную группу
  3. Таблица объединения точек безопасности группы
  4. Специальная таблица чисел BitMask, которая содержит записи для значений ^ 2. Таким образом, есть одна запись для 2 (2) и две записи для трех (2 и 1). Это избавляет нас от необходимости каждый раз вычислять значения.

Сначала мы определяем, вошел ли пользователь в систему. Если нет, мы возвращаем анонимную авторизацию для точки безопасности.

Далее мы определяем, является ли пользователь членом какой-либо группы, связанной с точкой безопасности, с помощью простого EXISTS с использованием JOIN. Если нет, мы возвращаем значение, связанное с аутентифицированным пользователем. Для большинства анонимных и аутентифицированных значений по умолчанию в нашей системе установлено значение 1, поскольку мы требуем, чтобы вы относились к определенным группам.

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

Если пользователь является членом одной или нескольких групп, то мы выбираем отдельные значения из таблицы BitMask для каждого из значений, определенных для групп. Например, если вы принадлежали к трем группам и имели один уровень авторизации 8, один с 12 и последний с 36, наш выбор по таблице битовых масок вернул бы 8, 8 и 4 и 4 и 32 соответственно. Делая различное, мы получаем числа 4, 8 и 32, которые корректно маскируют биты до 101100.

Это значение возвращается как уровень авторизации пользователя и обрабатывается веб-сайтом.

Имеет смысл?

...