如何扩展AuthorizeAttribute并检查用户的角色

Bre*_*ogt 4 c# asp.net asp.net-mvc asp.net-mvc-3 asp.net-mvc-2

我正忙着为我的动作方法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();
   }
}
Run Code Online (Sandbox Code Playgroud)

这是我的角色枚举:

public enum Role
{
   Administrator = 1,
   SuperAdministrator = 2
}
Run Code Online (Sandbox Code Playgroud)

我的行动方法:

[MyAuthorize(Roles = Role.Administrator|Role.SuperAdministrator)]
public ActionResult Create()
{
   return View();
}
Run Code Online (Sandbox Code Playgroud)

我没有使用Roles ="Administrator,SuperAdministrator"的原因是角色是硬编码的.如果角色名称更改,我不希望有100个地方可以更改.

根据我的方法,当它到达if(Roles!= 0)然后Roles总值为3时,我如何检查这两个角色是否在特定用户的用户角色列表中?

我在这里做得对吗?如果不是,我将如何实施呢?它不一定是我做的方式.

Tom*_*mas 6

这岂不是更好,如果MyAuthorizeAttribute接受一个I​​List(或类似),这样它既是类型安全的,但你不必使用位标志.如果你想保存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<string>(user.Identity.Name, StringComparer.OrdinalIgnoreCase))
        {
            return false;
        }*/
        if ((RoleList.Length > 0) && !RoleList.Select(p=>p.ToString()).Any<string>(new Func<string, bool>(user.IsInRole)))
        {
            return false;
        }
        return true;
    }

}
Run Code Online (Sandbox Code Playgroud)

控制器:

[MyAuthorize(RoleList = new []{Role.Administrator , Role.SuperAdministrator} )]
    public ActionResult Create()
    {
        return View();
    }
Run Code Online (Sandbox Code Playgroud)


Tom*_*han 3

如果我理解正确,这里的问题不是继承AuthorizeAttribute,而是比较枚举值。您可能需要一个可以用作位标志的枚举类型 - 如果是这样,请查看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, i.e. 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(); 
}
Run Code Online (Sandbox Code Playgroud)

为了使比较更容易,您可以在枚举上使用以下扩展方法:

public static class RolesExtensions
{
    public static bool HasAnyOf(this Roles r1, Roles roles)
    {
        return (r1 & roles) > 0;
    }
}
Run Code Online (Sandbox Code Playgroud)