我有一个关于自定义授权属性(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表达式或数组创建表达式
我是否可以使用角色列表作为枚举作为属性参数来实现此目的?
答案 0 :(得分:1)
属性是元数据,必须在编译时知道,因此必须为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()
{
....
}
答案 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();