简体   繁体   中英

Custom MVC AuthorizeAttribute that allows for multiple role membership

I've got a custom AuthorizeAttribute class created to handle granular authorization in my MVC4 app.

This is the class:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class isAuthorized : AuthorizeAttribute
{
    public oRoles enRole;

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        var authorized = base.AuthorizeCore(httpContext);
        string test = enRole.ToString();
        if (!authorized)
        {
            // The user is not authenticated
            return false;
        }

        var user = httpContext.User;

        bool bFlag = AuthCheck.CheckUser(httpContext, enRole);
        if (bFlag) // I know this is a lot of code; it's for debugging purposes
            return true;

        return false;
    }
}

I've got the following enum declared to allow code helping:

public enum oRoles
{
    StudentSelfPassword = 1,
    StaffSelfPassword = 2,
    StudentLookup = 3,
    StudentChangeRequest = 4,
    StudentAdmin = 5,
    StaffLookup = 6,
    StaffChangeRequest = 7,
    StaffAdmin = 8,
    ChangeQueueApproval = 9
}

In my controller I call the AuthorizeAttribute by:

    [isAuthorized(enRole = oRoles.StudentLookup)]
    [isAuthorized(enRole = oRoles.StaffLookup)]
    [isAuthorized(enRole = oRoles.StudentChangeRequest)]
    [isAuthorized(enRole = oRoles.StaffChangeRequest)]

When I run it through the debugger, The first isAuthorized runs and returns true (as it should) and continues to the second isAuthorized where it returns false then immediately asks me to authenticate. I was expecting it to allow because the first condition was true. However, it appears my assumption was not right.

Originally, I had Roles = "change,admin" which were groups in the domain and it worked but the groups needed to be dynamic in their assignment and not static. I was able to push multiple items ok there. Is that because it was being sent as a string?

Is there a way to essentially do a isAuthorized(...) || isAuthorized(...) || isAuthorized(...) so that if one condition is true it's validated as ok?

In your attribute, rather than having a property with a single oRole, can you have a list or array of roles. And rather than putting a number of attributes, decorate your method with one attribute but pass it an array of allowed roles.

[isAuthorized(enRoles = new oRoles[]{oRoles.StudentLookup, oRoles.StaffLookup })]

An example of creating an attribute that takes multiple values is here

Then in your authorization checking code you can check against all the allowed list that has been provided. Something like the code below

 bool bFlag = enRoles.ToList().Any( r => AuthCheck.CheckUser(httpContext, r));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM