MVC 5自定义属性枚举列表作为参数

时间:2018-10-31 13:36:50

标签: c# asp.net asp.net-mvc-5

我有一个关于自定义授权属性(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 :(得分:1)

属性是元数据,必须在编译时知道,因此必须为conststatic 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()
{
    ....
}

答案 1 :(得分:0)

这是设计使然,我只看到一种在Xunit中解决该问题的方法。当使用其inlinedata属性创建参数化测试用例(理论)时,它们具有类似的问题。他们介绍了可能使用反射来处理它的classdata和memberdata属性。有关其他人如何使用它的信息,请参见以下帖子:http://hamidmosalla.com/2017/02/25/xunit-theory-working-with-inlinedata-memberdata-classdata/

答案 2 :(得分:0)

花了很多时间试图通过避免枚举标志找出解决该问题的方法,并阅读了Stephen Muecke的回答后,得出结论,我必须重构整个授权实现。因此,如果有人尝试实现类似的授权逻辑,请避免使用带有枚举角色的静态列表,并从一开始就使用标志。 here发布了一个非常有用的答案,其中包含有关枚举标志的说明。

因此,这是我要做的更改。

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

创建一个const枚举,其中包含有权执行操作的角色

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();