Безопасно ли использовать отражения и перечисления для логического контроля доступа к приложениям MVC? - PullRequest
7 голосов
/ 17 декабря 2011

Пытаясь управлять доступом к веб-сайту, я создал несколько необходимых объектов enter image description here

Цель состоит в том, чтобы использовать пользовательский атрибут разрешения для некоторого метода действия контроллера моего приложения MVC.

[Permissions(PermissionType.SomePermissionName, CrudType.CanDelete)]
public ActionResult SomeAction()
{
}

Для этой операции у меня есть два перечисления

[Flags]
public enum CrudType
{
    CanCreate = 0x1,
    CanRead = 0x2,
    CanUpdate = 0x4,
    CanDelete = 0x8,
}

[Flags]
public enum PermissionType
{
   SomePermissionName = 0x1,
   //... 
}

Теперь я хочу, чтобы описанный ниже метод проверял права доступа

public static bool CanAccess(RolePermissions rp, CrudType crudType)
{
    var pInfo = rp.GetType().GetProperties();
    var res = pInfo.FirstOrDefault(x => x.Name == crudType.ToString());
    if(res != null)
    {
        return Convert.ToBoolean(res.GetValue(rp, null));
    }
    return false;
}

Это работает хорошо, но безопасно лииспользовать отражение здесь?Это хороший стиль?Еще один вопрос касается такого фрагмента кода

var permission = PermissionService.GetByName(permissionType.ToString());

Здесь я пытаюсь получить объект разрешения из базы данных, используя некоторую именованную константу из перечисления PermissionType.В обоих случаях правильная работа зависит от отношений между перечислениями и некоторыми полями таблицы или записями.С другой стороны у меня есть хороший механизм управления логикой (как мне кажется).Это хороший способ?

Ответы [ 2 ]

3 голосов
/ 17 декабря 2011

ДРУГОЕ РЕДАКТИРОВАНИЕ
В вашем случае имеет смысл создать свойство ExistingPermissions только для чтения для класса RolePermissions и выполнить слияние четырех логических значений в один CrudType в получателе этого свойства. Тогда вы можете просто сделать rp.ExistingPermissions.HasFlag(permissionToCheck).

EDITED

Спасибо @DevDelivery за указание на проблему - хороший улов. К сожалению, фиксированное решение не так красиво, как я надеялся, поэтому в этом случае может иметь смысл использовать подход @ DevDelivery.

Поскольку у вас есть CrudType как «битовые поля», вы можете использовать более чистый подход (меньше кода и лучшую читаемость):

public static bool CanAccess(RolePermissions rp, CrudType permissionToCheck)
{
    CrudType existingPermissions = 
                                SetPermissionFlag(CrudType.CanCreate, rp.CanCreate) |
                                SetPermissionFlag(CrudType.CanRead, rp.CanRead) | 
                                SetPermissionFlag(CrudType.CanUpdate, rp.CanUpdate) |
                                SetPermissionFlag(CrudType.CanDelete, rp.CanDelete);

    return existingPermissions.HasFlag(permissionToCheck);
}

public static CrudType SetPermissionFlag(CrudType crudType, bool permission)
{
    return (CrudType)((int)crudType * Convert.ToInt32(permission));
}

Недостаток по сравнению с вашим решением состоит в том, что вам придется изменить этот метод на случай, если вы добавите больше операций (к существующим CanRead и т. Д.).

1 голос
/ 17 декабря 2011

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

Кроме того, этот код очень сложен для понимания, поэтому его трудно поддерживать.

Здесь есть только 4 варианта для проверки. Простой оператор переключения проще, быстрее и чище.

Использование рефлексии имеет смысл, если вы пытаетесь разрешить изменения в базе данных или сторонним компонентам вводить новые разрешения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...