Benutzerdefiniertes Autorisierungsattribut für ASP.NET MVC 4 mit Berechtigungscodes (ohne Rollen)


121

Ich muss den Zugriff auf Ansichten basierend auf Benutzerberechtigungsstufen (es gibt keine Rollen, nur Berechtigungsstufen für CRUD-Betriebsebenen, die Benutzern zugewiesen sind) in meiner MVC 4-Anwendung steuern.

Als Beispiel; Unter dem AuthorizeUser befindet sich mein benutzerdefiniertes Attribut, das ich folgendermaßen verwenden muss:

[AuthorizeUser(AccessLevels="Read Invoice, Update Invoice")]
public ActionResult UpdateInvoice(int invoiceId)
{
   // some code...
   return View();
}


[AuthorizeUser(AccessLevels="Create Invoice")]
public ActionResult CreateNewInvoice()
{
  // some code...
  return View();
}


[AuthorizeUser(AccessLevels="Delete Invoice")]
public ActionResult DeleteInvoice(int invoiceId)
{
  // some code...
  return View();
}

Ist es möglich, dies so zu tun?

Antworten:


243

Ich könnte dies mit einem benutzerdefinierten Attribut wie folgt tun.

[AuthorizeUser(AccessLevel = "Create")]
public ActionResult CreateNewInvoice()
{
    //...
    return View();
}

Benutzerdefinierte Attributklasse wie folgt.

public class AuthorizeUserAttribute : AuthorizeAttribute
{
    // Custom property
    public string AccessLevel { get; set; }

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        var isAuthorized = base.AuthorizeCore(httpContext);
        if (!isAuthorized)
        {                
            return false;
        }

        string privilegeLevels = string.Join("", GetUserRights(httpContext.User.Identity.Name.ToString())); // Call another method to get rights of the user from DB

        return privilegeLevels.Contains(this.AccessLevel);           
    }
}

Sie können einen nicht autorisierten Benutzer in Ihrem Benutzer umleiten, AuthorisationAttributeindem Sie die folgende HandleUnauthorizedRequestMethode überschreiben :

protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
    filterContext.Result = new RedirectToRouteResult(
                new RouteValueDictionary(
                    new
                        { 
                            controller = "Error", 
                            action = "Unauthorised" 
                        })
                );
}

Ich habe Ihr Beispiel für HandleUnauthorizedRequest ausprobiert, aber wenn ich das RouteValueDictionary spezifiziere, wird nur eine Route an mich weitergeleitet, die nicht vorhanden ist. Es hängt die Route an, auf die ich den Benutzer umleiten möchte, auf die Route, auf die der Benutzer zugreifen möchte ... si Ich erhalte Folgendes: localhost: 9999 / admin / Home, wenn ich localhost wollte: 9999 / Home
Marin

1
@Marin Versuchen Sie, area = string.Empty im RouteValueDictionary hinzuzufügen
Alex

30
Ich habe gestimmt, aber dann habe ich am Ende "if (Bedingung) {return true;} else {return false;}" gesehen ....
GabrielBB

1
@Emil Ich würde einfach den Booleschen Wert zurückgeben, den mir die String.Contains-Methode gegeben hat. Aber das ist irrelevant, ich habe nicht abgelehnt, ich habe nur nicht gestimmt, hehe.
GabrielBB

2
.Name.ToString()ist redundant, da die NameEigenschaft bereits Zeichenfolge ist
FindOutIslamNow

13

Hier ist eine Modifikation für die prev. Antworten. Der Hauptunterschied besteht darin, dass der Benutzer, wenn er nicht authentifiziert ist, die ursprüngliche Methode "HandleUnauthorizedRequest" verwendet, um zur Anmeldeseite umzuleiten:

   protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {

        if (filterContext.HttpContext.User.Identity.IsAuthenticated) {

            filterContext.Result = new RedirectToRouteResult(
                        new RouteValueDictionary(
                            new
                            {
                                controller = "Account",
                                action = "Unauthorised"
                            })
                        );
        }
        else
        {
             base.HandleUnauthorizedRequest(filterContext);
        }
    }

3

Vielleicht ist dies für jeden in der Zukunft nützlich. Ich habe ein benutzerdefiniertes Berechtigungsattribut wie das folgende implementiert:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public class ClaimAuthorizeAttribute : AuthorizeAttribute, IAuthorizationFilter
{
    private readonly string _claim;

    public ClaimAuthorizeAttribute(string Claim)
    {
        _claim = Claim;
    }

    public void OnAuthorization(AuthorizationFilterContext context)
    {
        var user = context.HttpContext.User;
        if(user.Identity.IsAuthenticated && user.HasClaim(ClaimTypes.Name, _claim))
        {
            return;
        }

        context.Result = new ForbidResult();
    }
}

0

Wenn Sie die WEB-API mit Ansprüchen verwenden, können Sie Folgendes verwenden:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
public class AutorizeCompanyAttribute:  AuthorizationFilterAttribute
{
    public string Company { get; set; }

    public override void OnAuthorization(HttpActionContext actionContext)
    {
        var claims = ((ClaimsIdentity)Thread.CurrentPrincipal.Identity);
        var claim = claims.Claims.Where(x => x.Type == "Company").FirstOrDefault();

        string privilegeLevels = string.Join("", claim.Value);        

        if (privilegeLevels.Contains(this.Company)==false)
        {
            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized, "Usuario de Empresa No Autorizado");
        }
    }
}
[HttpGet]
[AutorizeCompany(Company = "MyCompany")]
[Authorize(Roles ="SuperAdmin")]
public IEnumerable MyAction()
{....
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.