简体   繁体   中英

How to authorize users more than once using custom authorize attribute?

I have a custom authorize attribute class to check isAuthorize twice.

What I want :

1) It will check first if the user is super admin or not. If he is , then he will be authorized .

2) If he is not , then it will check if he has a role named " Deal User ". If he is not then he will be unauthorized .

3) Now if the user is in a " Deal User " role , I want to check the user whether the user own the deal or not. So I check into database if the user owns that deal . If he owns , then he will be authorized . Otherwise he will be Unauthorized .

public class DealManageCustomAuthorizeAttribute : AuthorizeAttribute

{

    private static ApplicationDbContext Context = new ApplicationDbContext();
    private static UserStore<ApplicationUser> userStore = new UserStore<ApplicationUser>(Context);
    private UserManager<ApplicationUser> userManager = new UserManager<ApplicationUser>(userStore);

    private enum Result
    {
        Authorize,
        Unauthorize,
        InternalServerError
    }

    public override void OnAuthorization(HttpActionContext actionContext)
    {

        var result = AuthorizeRequest(actionContext);
        if (result == Result.Authorize)
        {
            return;
        }
        else
        {
            HandleUnauthorizedRequest(actionContext);
        }

    }

    protected override void HandleUnauthorizedRequest(System.Web.Http.Controllers.HttpActionContext actionContext)
    {
        //Code to handle unauthorized request
        base.HandleUnauthorizedRequest(actionContext);
    }

    private Result AuthorizeRequest(System.Web.Http.Controllers.HttpActionContext actionContext)
    {
        base.Roles = "Super Admin";
        bool authorized = base.IsAuthorized(actionContext);
        if (!authorized)
        {
            try
            {

                base.Roles = "Deal User";

                bool auth = base.IsAuthorized(actionContext);

                if (!auth)
                {
                    return Result.Unauthorize;
                }

                Uri uri = actionContext.Request.RequestUri;
                Guid dealId = new Guid(HttpUtility.ParseQueryString(uri.Query).Get("dealId"));
                string userId = HttpContext.Current.User.Identity.GetUserId();

                var retval = new Deal(Common.Common.TableSureConnectionString).CheckDealByIdAndUserId(dealId, userId);

                if (retval)
                {
                    return Result.Authorize;
                }
                return Result.Unauthorize;
            }
            catch (Exception)
            {
                return Result.InternalServerError;
            }
        }
        return Result.Authorize;
    }

}

I wrote the code and it is working. But I want to know whether it is the correct way to authorize users ?

It is unclear exactly why your custom authorize attribute is not working, but it is clear that its implementation is overly complex.

The AuthorizeAttribute has simple boolean function IsAuthorized that you can (and should) override to return whether or not the user is authorized. The base implementation already checks

  1. Whether the user is logged in.
  2. Whether the user is in one of the supplied roles.

so all you need to do is add additional logic when the user is in the Deal User role.

You should never access the static HttpContext.Current member in Web API/MVC. In this particular case, the actionContext is being passed in as a parameter, which you can (and should) use.

using Microsoft.AspNet.Identity;
using System;
using System.Linq;
using System.Net.Http;
using System.Security.Principal;
using System.Web.Http;
using System.Web.Http.Controllers;

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true)]
public class DealManageCustomAuthorizeAttribute : AuthorizeAttribute
{
    public DealManageCustomAuthorizeAttribute()
    {
        // Set the Super Admin and Deal User roles
        this.Roles = "Super Admin,Deal User";
    }

    protected override bool IsAuthorized(HttpActionContext actionContext)
    {
        // This checks whether the user is logged in, and whether
        // they are in the Super Admin or Deal User role.
        var isAuthorized = base.IsAuthorized(actionContext);

        IPrincipal user = actionContext.ControllerContext.RequestContext.Principal;

        // Special case - user is in the Deal User role
        if (isAuthorized && user.IsInRole("Deal User"))
        {

            var queryString = actionContext.Request.GetQueryNameValuePairs()
                .ToDictionary(kv => kv.Key, kv => kv.Value, StringComparer.OrdinalIgnoreCase);

            // Ensure the query string contains the key "dealId"
            if (!queryString.ContainsKey("dealId"))
            {
                return false;
            }

            Guid dealId;
            if (!Guid.TryParse(queryString["dealId"], out dealId))
            {
                // If the Guid cannot be parsed, return unauthorized
                return false;
            }

            // Now check whether the deal is authorized.
            var userId = user.Identity.GetUserId();

            return new Deal(Common.Common.TableSureConnectionString)
                .CheckDealByIdAndUserId(dealId, userId);
        }

        return isAuthorized;
    }
}

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