我正在尝试使授权接受为枚举或smart enum角色 这样我就不必调试魔术字符串及其错别字
但是我总是遇到以下两个错误:
属性构造函数参数“角色”具有类型“角色[]”,这不是有效的属性参数类型
属性参数必须是属性参数类型的常量表达式,typeof表达式或数组创建表达式
这是我的代码:
AuthorizeRoles.cs
public class AuthorizeRoles : AuthorizeAttribute
{
public AuthorizeRoles(params Role[] roles)
{
string allowed = string.Join(", ", roles.ToList().Select(x => x.Name));
Roles = allowed;
}
}
Role.cs
public class Role
{
public readonly string Name;
public enum MyEnum // added
{
Admin,
Manager
}
public static readonly Role Admin = new Role("Admin");
public static readonly Role Manager = new Role("Manager");
public Role(string name)
{
Name = name;
}
public override string ToString()
{
return Name;
}
在控制器内部,我做到了
[AuthorizeRoles(Role.Admin, Role.Manager)]
[AuthorizeRoles(Role.MyEnum.Admin)] // added
public IActionResult Index()
{
return Content("hello world");
}
我已经看过这些答案,但是没有用
答案 0 :(得分:3)
由于CLR约束(属性如何存储在元数据中),属性参数只能是原始类型或这些类型(和Type
)的数组。您不能将Role
(自定义对象)传递给属性。
枚举有效,但是编译器无法将您的枚举(Role.MyEnum
)转换为Role
的类型,即AuthorizeRoles
。所以这是编译器错误。
您可以猜到,解决方案是创建一个采用Role.MyEnum
数组的构造函数,如下所示:
public class AuthorizeRoles : Attribute
{
public string Roles { get; private set; }
public AuthorizeRoles(params Role.MyEnum[] roles)
{
string allowed = string.Join(", ", roles);
Roles = allowed;
}
}
public class Role
{
public readonly string Name;
public enum MyEnum
{
Admin,
Manager
}
public Role(string name)
{
Name = name;
}
public override string ToString()
{
return Name;
}
}
// ...
[AuthorizeRoles(Role.MyEnum.Admin)]
public IActionResult Index()
{
// ...
}
答案 1 :(得分:2)
在构造函数AuthorizeRoles类中,您使用Role类的数组,但在属性[AuthorizeRoles(Role.MyEnum.Admin)]中,您使用类型为MyEnum的参数。如果要使用枚举,则必须使用MyEnum类型的参数创建AuthorizeRoles类构造函数。
答案 2 :(得分:1)
它确实很烂,但实际上您可以最接近它的方法是:
public static class Roles
{
public const string Admin = "Admin";
public const string Manager = "Manager";
}
然后:
[Authorize(Roles = Roles.Admin + "," + Roles.Manager)]
在常量字符串组合和就地字符串连接之间,它们仍然是“常量表达式”。基本上,您无法做的事情是需要运行诸如string.Join
之类的方法。这就是使用属性时的游戏中断。
答案 3 :(得分:0)
使用常量作为策略名称并使用授权策略
// startup.cs
services.AddAuthorization(options =>
{
options.AddPolicy(PolicyConstants.Admin, policy =>
{
// Allowed to access the resource if role admin or manager
policy.RequireClaim(JwtClaimTypes.Role, new[] { PolicyConstants.Admin, PolicyConstants.Manager });
// Or use LINQ here
policy.RequireAssertion(c =>
{
// c.User.Claims
});
}
在控制器中使用策略名称
[Authorize(PolicyConstants.Admin)]
public class TestController
{
// here also you can use specific policy and for controller, you can use other policy. It will match Action Level policy first and then match controller policy.
public IActionResult Index()
{
}
}