2013-02-15 5 views
5

Ich habe eine Windows authentifizierte MVC-Anwendung mit einer Repository-Schicht. Die gesamte Interaktion des Controllers mit der Datenbank erfolgt über das Repository. Jeder Controller weist einen Verweis auf das Repository:Muster für die Autorisierung im Repository-Layer der MVC-Anwendung

public class PostController : Controller 
{ 
    private Repository db = new Repository(); 

    [HttpPost] 
    public ActionResult DeletePost(int id) 
    { 
     // Authorize that the user is allowed to delete this post... 

     db.DeletePost(id); 
    } 
} 

Meine Frage ist, ob es ein guter Weg ist meine Berechtigungslogik in die Repository-Schicht zu bewegen. Ich möchte, dass die Funktion Repository.DeletePost() sich weigert, Beiträge zu löschen, die nicht vom authentifizierten Benutzer erstellt wurden. Das Problem ist, dass mein Repository nicht weiß, wer der authentifizierte Benutzer ist. Der Controller weiß (über Controller.User).

die Controller.User in den Repository Konstruktor nicht funktioniert, weil die Controller.User ist offenbar nicht zu dem Zeitpunkt definiert, wenn der Konstruktor aufgerufen wird.

Wie kann ich die Repository darüber informieren, wer der authentifizierte Benutzer ist? Wäre es am besten, die Repository innerhalb jeder Aktion zu konstruieren? Oder ist es eine schlechte Idee, es in der Repository-Ebene zu behandeln?

Antwort

1

Gute Vorschläge von @BigDaddy und @ChrisPratt.

Ich löste dies durch Erstellen eines Basis-Controllers, ähnlich wie this answer. Meine Basis-Controller-Klasse wie folgt aussieht:

public class BaseController : Controller 
{ 
    private ILog _log; 
    private Repository _db; 

    protected Repository Db 
    { 
     get 
     { 
      return _db ?? (_db = new Repository(User)); 
     } 
    } 

    protected ILog Log 
    { 
     get 
     { 
      return _log ?? (_log = LogManager.GetLogger(this.GetType())); 
     } 
    } 
} 

Alle meine Controller von dieser Klasse erben und haben integrierten Zugriff auf einen faulen belasteten Repository, die einen Verweis auf die derzeit authentifizierten Benutzer hat.

+0

Dies ist, was ich eigentlich mache, aber ich denke, es hat nicht genug "Entkopplung", da unser Repository jetzt an unseren Benutzer gebunden ist, der eine Art Admin sein könnte, der nichts tun könnte, wenn Sie nicht gerechnet hätten dafür bei jedem Schritt – Worthy7

1

Just do so etwas wie:

db.DeletePostForUser(id, User.Identity.UserId); 

Dann in Ihrem Repository:

public void DeletePostForUser(int id, int userId) 
{ 
    var post = context.Posts.SingleOrDefault(m => m.PostId == id && m.User.UserId == userId) 
    if (post != null) 
    { 
     context.Posts.Remove(post); 
     context.SaveChanges(); 
    } 
} 
+0

Guter Vorschlag ... Ich bin mit etwas anderem gegangen, weil es in meinem Repository oft vorkommen kann, wenn ich wissen will, wer der 'Benutzer' ist, und ich möchte es vermeiden, so viele Unterschriften hinzuzufügen . – Eric

+1

@Chris aber sollten unsere Repos die Autorisierung durchführen? – uriDium

+0

Im Grunde ist @uriDium richtig, Repositorys sind nur zum Abrufen und Einstellen. Sie sind nicht da, um vor dem Benutzer zu schützen, der es tut. Das ist die Aufgabe der Domain. Was ist, wenn Sie plötzlich einige Änderungen in der Datenbank von einem Administrator vornehmen müssen? Wer darauf zugreift, spielt keine Rolle, wenn Sie den Zugriff beschränken wollen, dann beschränken Sie den Zugriff auf eine niedrigere Ebene in den Controllern. Dann würde die Serviceschicht (die sich in der Steuerung befinden könnte) die Arbeit der Validierung durchführen, wenn der Benutzer diese Änderungen vornehmen kann (selbst wenn es den Aufruf der Datenbank aus irgendeinem seltsamen Grund erfordert). – Worthy7

3

Oder ist es eine schlechte Idee, es in der Repository-Schicht zu behandeln?

Ich denke, der Controller ist ein besserer Ort für Ihre Genehmigung. Lassen Sie das Repository ein Gateway zu den Daten sein und der Controller ein Gatekeeper für Ihre Anwendung sein. Ich würde erwarten, Autorisierungs-/Authentifizierungslogik so früh wie möglich im Lebenszyklus zu sehen.

+0

Ich kann das schätzen ... Ich werde sehen, wie es sich anfühlt, meine Autorisierungslogik in das Repository zu schreiben. Wenn es sich schmutzig anfühlt, werde ich wahrscheinlich auf Ihren Vorschlag zurückkommen. – Eric

+0

Ich habe ein System mit WebInterface & WebService, natürlich brauche ich zwei Authentifizierungslogiken, aber ich möchte nicht den Autorisierungscode duplizieren ... wie lösen Sie das? –

+1

Wenn Sie nicht auf beiden Ebenen autorisieren, wie sonst können Sie den Zugriff kontrollieren? Wahrscheinlich möchten Sie sich auf dem UI-Layer authentifizieren und die Authentifizierung auf dem Service-Layer überprüfen. Autorisieren Sie dann auf der UI- und Service-Ebene. –

Verwandte Themen