如何扩展AuthorizeAttribute并检查用户的角色
我正忙着为我的动作方法MyAuthorizeAttribute编写自己的自定义属性,我仍在忙于编写代码,这里是我的部分代码:
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] public class MyAuthorizeAttribute : AuthorizeAttribute { public new Role Roles; public override void OnAuthorization(AuthorizationContext filterContext) { base.OnAuthorization(filterContext); if (Roles != 0) // Did it this way to see what the value of Roles was return; // Here I am going to get a list of user roles // I'm doing my own database calls filterContext.Result = new HttpUnauthorizedResult(); } }
这是我的角色枚举:
public enum Role { Administrator = 1, SuperAdministrator = 2 }
我的行动方法:
[MyAuthorize(Roles = Role.Administrator|Role.SuperAdministrator)] public ActionResult Create() { return View(); }
我没有使用Roles =“Administrator,SuperAdministrator”的原因是角色是硬编码的。 如果角色名称更改,我不希望有100个地方可以更改。
根据我的方法,当它到达if(Roles!= 0)然后Roles总值为3时,我如何检查这两个角色是否在特定用户的用户角色列表中?
我在这里做得对吗? 如果不是,我将如何实现这一点? 它不一定是我做的方式。
如果MyAuthorizeAttribute接受IList(或类似的),那么它是不是更好,这样既有类型安全,但你不必使用位标志。 如果你想保存reult,那么位标志很棒,但这是另一种方式。
编辑(现在有例子):
Attribute: [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] public class MyAuthorizeAttribute : AuthorizeAttribute { public Role[] RoleList { get; set; } protected override bool AuthorizeCore(HttpContextBase httpContext) { if (httpContext == null) { throw new ArgumentNullException("httpContext"); } IPrincipal user = httpContext.User; if (!user.Identity.IsAuthenticated) { return false; } //Only role access is implemented here /*if ((this._usersSplit.Length > 0) && !this._usersSplit.Contains(user.Identity.Name, StringComparer.OrdinalIgnoreCase)) { return false; }*/ if ((RoleList.Length > 0) && !RoleList.Select(p=>p.ToString()).Any (new Func(user.IsInRole))) { return false; } return true; } }
控制器:
[MyAuthorize(RoleList = new []{Role.Administrator , Role.SuperAdministrator} )] public ActionResult Create() { return View(); }
如果我理解正确,那么你的问题不在于inheritanceAuthorizeAttribute
,而在于比较枚举值。 您可能需要一个可用作位标志的枚举类型 – 如果是这样,请查看C#编程指南中有关枚举类型的部分,尤其是第二部分“枚举类型为位标志”。
澄清一下:
而不只是检查Roles!=0
,你现在可以做这样的事情:
public override void OnAuthorization(AuthorizationContext filterContext) { base.OnAuthorization(filterContext); // Here you get an enum indicating the roles this user is in. The method // converts the db information to a Role enum before it is returned. // If the user is not authenticated, the flag should not be set, ie equal 0. Role userRole = GetUserRolesFromDatabase(); // Bitwise comparison of the two role collections. if (Roles & userRole > 0) { // The user is in at least one of the roles in Roles. Return normally. return; } // If we haven't returned yet, the user doesn't have the required privileges. new HttpUnauthorizedResult(); }
为了使比较更容易,您可以在枚举上使用以下扩展方法:
public static class RolesExtensions { public static bool HasAnyOf(this Roles r1, Roles roles) { return (r1 & roles) > 0; } }