Как изменить атрибут Authorize, чтобы разрешить группу ролей пользователей в MVC 3

В моем приложении MVC3 wep я расширил атрибут Authorize, как показано ниже.

public class MyAuthorizeAttribute : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        if (Authenticate.IsAuthenticated() && httpContext.User.Identity.IsAuthenticated)
        {
            var authCookie = httpContext.Request.Cookies[FormsAuthentication.FormsCookieName];
            if (authCookie != null)
            {
                var ticket = FormsAuthentication.Decrypt(authCookie.Value);
                var roles = ticket.UserData.Split('|');
                var identity = new GenericIdentity(ticket.Name);
                httpContext.User = new GenericPrincipal(identity, roles);
            }
        }
        return base.AuthorizeCore(httpContext);
    }

    public override void OnAuthorization(AuthorizationContext filterContext)
    {

        if (!Authenticate.IsAuthenticated())
            HandleUnauthorizedRequest(filterContext);


        base.OnAuthorization(filterContext);

    }

В своих действиях я использую его как

    [MyAuthorize(Roles = "Member,Inspector,SalesRep,Admin,SuperAdmin")]
    public ActionResult OrderUpload()

Теперь я должен указать каждую роль пользователя в каждом действии. Я хотел бы указать что-то вроде ниже

    [MyAuthorize(Roles = "Member")]
    public ActionResult OrderUpload()

и это должно разрешить любую роль пользователя, равную или выше «Член». Таким образом, «Продавец» должен быть разрешен, тогда как «Посетитель», который находится ниже «Участника», не должен быть разрешен.

Все роли пользователей перечисляются с увеличением числа

public enum UserAccountType
{
    Visitor = 5,
    Member = 10,
    Inspector = 15,
    SalesRep = 20,
    Admin = 25,
    SuperAdmin = 30
}

Как мне изменить MyAuthorizeAttribute, чтобы это работало?

Спасибо


person Nathan    schedule 30.11.2012    source источник


Ответы (2)


Вот мой рабочий код

public class MyAuthorizeAttribute : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        if (Authenticate.IsAuthenticated() && httpContext.User.Identity.IsAuthenticated)
        {
            var authCookie = httpContext.Request.Cookies[FormsAuthentication.FormsCookieName];
            string[] roles = null;

            if (authCookie != null)
            {
                var ticket = FormsAuthentication.Decrypt(authCookie.Value);
                roles = ticket.UserData.Split('|');
                var identity = new GenericIdentity(ticket.Name);
                httpContext.User = new GenericPrincipal(identity, roles);
            }

            if (Roles == string.Empty)
                return true;

            //Assuming Roles given in the MyAuthorize attribute will only have 1 UserAccountType - if more than one, no errors thrown but will always return false
            else if ((UserAccountType)Enum.Parse(typeof(UserAccountType), roles[0]) >= (UserAccountType)Enum.Parse(typeof(UserAccountType), Roles))
                return true;
            else
                return false;
        }
        else
            return false;

        //return base.AuthorizeCore(httpContext);
    }

    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        if (!Authenticate.IsAuthenticated())
            HandleUnauthorizedRequest(filterContext);

        base.OnAuthorization(filterContext);
    }
}
person Nathan    schedule 11.12.2012

Я использую не AuthorizeAttribute, а ActionFilter (это только я, и именно так я его узнал), но я бы добавил свойство в AuthorizeAttribute, которое обновляется, когда атрибут запускается до действия.

public class MyAuthorizeAttribute : AuthorizeAttribute
{
    private string Role = "";

    public MyAuthorizeAttribute(string role){
        this.Role = role;
    }

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
          :
          :
          :
          // now do a check if the Role is authorized or not using your enum. 
          // return error page if not
          if(RoleisAuthorized)
            return; 
          else
            // error page

    }

    public override void OnAuthorization(AuthorizationContext filterContext)
    {
          :
          :
          :
    }
}

Теперь, когда вы получили роль, перейдите к ней из перечисления и сравните, разрешен ли роли доступ к странице или нет, если она не возвращает страницу с ошибкой. Так как я не знаком с OnAuthorization, я бы поместил процесс внутрь AuthorizeCore.

person gdubs    schedule 30.11.2012
comment
теперь, как мне преобразовать строку [Role] в мое перечисление? путем сравнения строк со всеми моими ролями перечисления? - person Nathan; 08.12.2012
comment
да. У меня есть свои роли на столе и в коллекции, поэтому я бы сделал sql типа EF. Но если вы используете перечисление, тогда да, ищите эту строку в перечислении. - person gdubs; 08.12.2012
comment
Я пробовал выше, он начал выдавать ошибки, где я не указал никаких Ролей. например. [MyAuthorize] Итак, я воспользовался вашей идеей и придумал свою. Я дал вам балл за идею. Смотрите ответ ниже - person Nathan; 11.12.2012