Несколько типов разрешений (ролей), хранящихся в базе данных в виде одиночного десятичного числа.

StackOverflow https://stackoverflow.com/questions/60204

  •  09-06-2019
  •  | 
  •  

Вопрос

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

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

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

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

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

«Лично я иногда использую помеченное перечисление разрешений.Таким образом, вы можете использовать побитовые операции AND, OR, NOT и 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).

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

Это было полезно?

Решение

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

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.

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

Другие советы

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

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

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

  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.

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

Имеет смысл?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top