2012-06-14 3 views
16

Ich habe eine Controller-Methode Edit aufgerufen, in der wir die Benutzerdaten bearbeiten können sie wie so geschaffen hatte ...ASP.NET MVC nur Attribut auf Benutzer bearbeiten ihren/seinen eigenen Inhalt

public ActionResult Edit(int id) 
{ 
    Submission submission = unit.SubmissionRepository.GetByID(id); 
    User user = unit.UserRepository.GetByUsername(User.Identity.Name); 

    //Make sure the submission belongs to the user 
    if (submission.UserID != user.UserID) 
    { 
     throw new SecurityException("Unauthorized access!"); 
    } 

    //Carry out method 
} 

Diese Methode funktioniert gut, aber es ist ein wenig unordentlich in jede Controller-Edit-Methode zu setzen. Jede Tabelle hat immer eine UserID, also habe ich mich gefragt, ob es eine einfachere Möglichkeit gibt, dies über ein [Authorize] Attribut oder einen anderen Mechanismus zu automatisieren, um den Code sauberer zu machen.

Antwort

24

Ja, könnten Sie, dass durch ein benutzerdefiniertes Attribut Autorisieren erreichen:

public class MyAuthorizeAttribute : AuthorizeAttribute 
{ 
    protected override bool AuthorizeCore(HttpContextBase httpContext) 
    { 
     var authorized = base.AuthorizeCore(httpContext); 
     if (!authorized) 
     { 
      return false; 
     } 

     var rd = httpContext.Request.RequestContext.RouteData; 

     var id = rd.Values["id"]; 
     var userName = httpContext.User.Identity.Name; 

     Submission submission = unit.SubmissionRepository.GetByID(id); 
     User user = unit.UserRepository.GetByUsername(userName); 

     return submission.UserID == user.UserID; 
    } 
} 

und dann:

[MyAuthorize] 
public ActionResult Edit(int id) 
{ 
    // Carry out method 
} 

und nehmen wir an, dass Sie diese Vorlage Instanz füttern müssen, die wir in den benutzerdefinierten geholt Attribut als Aktionsparameter, um zu vermeiden, die Datenbank erneut zu treffen, könnten Sie Folgendes tun:

public class MyAuthorizeAttribute : AuthorizeAttribute 
{ 
    protected override bool AuthorizeCore(HttpContextBase httpContext) 
    { 
     var authorized = base.AuthorizeCore(httpContext); 
     if (!authorized) 
     { 
      return false; 
     } 

     var rd = httpContext.Request.RequestContext.RouteData; 

     var id = rd.Values["id"]; 
     var userName = httpContext.User.Identity.Name; 

     Submission submission = unit.SubmissionRepository.GetByID(id); 
     User user = unit.UserRepository.GetByUsername(userName); 

     rd.Values["model"] = submission; 

     return submission.UserID == user.UserID; 
    } 
} 

und dann:

[MyAuthorize] 
public ActionResult Edit(Submission model) 
{ 
    // Carry out method 
} 
+1

Danke zu ermöglichen! Ich werde das generischer machen. Wie haben Vorlage haben eine Schnittstelle namens IUserOwnable, die eine UserID hat. Und dann übergeben Sie das Repository in das Attribut, wo es ein IUserOwnable holt und diese UserID des Benutzers mit der UserID des IUserOwnable verglichen –

+0

Sicher, dies könnte so generisch wie Sie möchten, um Ihre spezifischen Anforderungen entsprechen. –

+0

Netter Ansatz. Ich hüpfte, dass es jetzt ein eingebautes Attribut für das –

-1

Ich empfehle auf der AuthorizeAttribute lesen (siehe here). Haben Sie auch this Post gesehen? Es geht darüber hinaus, wie die Authentifizierungsattribute innards überschrieben werden und wie IPrincipal und IIdentity verwendet werden.

1

Ich würde vorschlagen, Sie ziehen die Logik aus der Aktion/Controller und bauen eine Domain-Klasse, um diese Logik zu behandeln.

Aktionsmethoden sollten sich nur mit dem Abrufen von Daten und dem Senden von Daten an die Ansicht befassen. Sie könnten etwas generisches erstellen, das Ihren Anforderungen entspricht, aber auch dem Principal für eine einzige Verantwortlichkeit folgen.

public class AuthorizedToEdit 
{ 
    protected override bool AuthorizeCore(string user, int itemId) 
    { 
     var userName = httpContext.User.Identity.Name; 

     var authUsers = SubmissionRepository.GetAuthoriedUsers(itemId); 

     return authUsers.Contains(user); 
    } 
} 

Dies würde auch Ihnen die Flexibilität, später haben so etwas wie Admin-Benutzer

Verwandte Themen