Перечисление пользовательских атрибутов MVC 5 в качестве параметра - PullRequest
0 голосов
/ 31 октября 2018

У меня проблема с пользовательским атрибутом авторизации (MVC 5) и списком перечислений, которые представляют роль пользователя. Сначала у меня есть этот пользовательский атрибут авторизации

[System.AttributeUsage(System.AttributeTargets.All, AllowMultiple = false, Inherited = true)]
public sealed class CustomAuthorizationAttribute : AuthorizeAttribute
{
    public Enums.Roles[] AllowedRoles { get; set; }
}

Перечисление ролей

public enum Roles
{
    uknown = 0,
    Admin= 100,
    Guest = 200,
}

Статический список, который я использую для ограничения доступа пользователей к определенным контроллерам и методам, которые я хочу использовать

public static class AuthorizationHelpers
{
   public static readonly Enums.Roles[] AccessToIndivindual = {
       Enums.Roles.Admin,
       Enums.Roles.Guest,
   };
}

В моем контроллере, когда я использую следующее и задаю список ролей перечисления, авторизация работает как положено

    [CustomAuthorization(AllowedRoles = new[] { Enums.Roles.Admin, Enums.Roles.Guest})]
public class HomeController
{
   ....
}

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

[CustomAuthorization(AllowedRoles = AuthorizationHelpers.AccessToIndivindual )]
public class HomeController
{
   ....
}

но каждый раз, когда я использую это, я получаю

Аргументом атрибута должно быть константное выражение, выражение typeof или выражение создания массива типа параметра атрибута

Есть ли способ использовать список ролей в качестве перечислений в качестве параметра атрибута для достижения этой цели?

Ответы [ 3 ]

0 голосов
/ 01 ноября 2018

Атрибуты являются метаданными и должны быть известны во время компиляции, поэтому должны быть const. Поле static readonly не является const, и массив, содержащий элементы, не может быть объявлен как const.

Если вы хотите использовать поле в качестве значения для AllowedRoles, то вам нужно будет использовать Flags enum.

[Flags]
public enum Roles
{
    uknown = 1,
    Admin= 2,
    Guest = 4,
}

и затем вы можете объявить const как

public const Roles _AccessToIndivindual = Roles.Admin | Roles.Guest;

и используйте его в своем CustomAuthorizationAttribute как

[CustomAuthorization(AllowedRoles = _AccessToIndivindual )]
public class HomeController()
{
    ....
}
0 голосов
/ 01 ноября 2018

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

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

public static class Enums
{
  [Flags]
  public enum Roles
  {
    uknown = 0,
    Admin= 1 << 1,
    Guest = 1 << 2
  }
}

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

public static class AuthorizationHelpers{
    public const Enums.Roles Can_Save_Product = Enums.Roles.Admin| Enums.Roles.Guest;
}

атрибут авторизации

[CustomAuthorization(Allowed_Roles = AuthorizationHelpers.Can_Save_Product )]
public class HomeController
{
     .....
}

и, наконец, в моем атрибуте CustomAuthorization

[System.AttributeUsage(System.AttributeTargets.All, AllowMultiple = false, Inherited = true)]
public sealed class CustomAuthorizationAttribute : AuthorizeAttribute
{
     public Enums.Roles Allowed_Roles { get; set; }
}

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

AuthorizationHelpers.Can_Save_Product.HasFlag(role.ToEnum<Enums.Roles>()))

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

this.Allowed_Roles.ToString().Split(',').Select(u=>u.Trim()).ToArray();
0 голосов
/ 31 октября 2018

Это сделано специально, и я видел только один способ, как это обойти в Xunit. У них похожая проблема при создании параметризованных тестовых случаев (теорий) с использованием их атрибута inlinedata. Они вводят атрибуты classdata и memberdata, которые, вероятно, используют отражение для его обработки. Смотрите следующий пост о том, как его используют другие: http://hamidmosalla.com/2017/02/25/xunit-theory-working-with-inlinedata-memberdata-classdata/

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