Как расширить AuthorizeAttribute и проверить роли пользователя - PullRequest
4 голосов
/ 25 февраля 2011

Я занят написанием своего собственного пользовательского атрибута для метода действия 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, как мне проверить, есть ли эти 2 роли в списке ролей пользователя для конкретного пользователя?

Я правильно здесь делаю? Если нет, то как бы я иначе это реализовал? Это не должно быть так, как я это сделал.

Ответы [ 2 ]

6 голосов
/ 25 февраля 2011

Не было бы лучше, если бы MyAuthorizeAttribute принял IList (или аналогичный) Таким образом, оба типа безопасны, но вам не нужно использовать битовые флаги. Битовые флаги хороши, если вы хотите сохранить результат, но это другой способ.

Редактировать (теперь с примерами):

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;
    }

}

Контроллер:

[MyAuthorize(RoleList = new []{Role.Administrator , Role.SuperAdministrator} )]
    public ActionResult Create()
    {
        return View();
    }
3 голосов
/ 25 февраля 2011

Если я правильно понимаю, ваша проблема здесь не в наследовании AuthorizeAttribute, а в сравнении значений enum. Возможно, вам нужен тип enum, который вы можете использовать в качестве битового флага - если это так, взгляните на раздел о типах перечисления в руководстве по программированию на 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(); 
}

Чтобы упростить сравнение, вы можете использовать следующий метод расширения в вашем перечислении:

public static class RolesExtensions
{
    public static bool HasAnyOf(this Roles r1, Roles roles)
    {
        return (r1 & roles) > 0;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...