Unity Inject Abhängigkeiten in MVC-Filter-Klasse mit Parametern

7

Ich verwende die Unity.MVC4 Abhängigkeitsinjektion für den Zugriff auf meine Dienste. Alles funktioniert wie es sollte, wenn ich in meinen Controller-Konstruktor einfüge, aber was ich jetzt tun möchte, ist property injection in meiner Filterklasse, damit ich von innen auf meine Datenbank zugreifen kann.

Bevor ich mit dieser Frage angefangen habe, habe ich gegoogelt und verschiedene Beispiele ausprobiert, aber ich konnte keine Lösung finden, die für mich funktioniert hat.

Bootstrapper.cs

%Vor%

Anwendungsstart

%Vor%

Arbeitsbeispiel

%Vor%

Der folgende Code, den ich Ihnen zeigen werde, ist für das Filterattribut, das ich für meine Aktionen verwenden möchte. Ich möchte einen Parameter des Typs String-Array übergeben, damit ich überprüfen kann, ob der aktuelle Benutzer auf die Aktion zugreifen darf.

In meiner Anwendung gibt es zwei Arten von Benutzern, Kontoinhaber und Gast. Alle Aktionen sind für Kontoinhaber vollständig geöffnet, für Gäste variieren sie jedoch von Aktion zu Aktion. Zum Beispiel kann eine Aktion erfordern mindestens eine von drei Berechtigungen (lesen, schreiben und bearbeiten).

Filter:

%Vor%

Wenn ich diesen Filter verwenden würde, würde er ungefähr so ​​aussehen ..

%Vor%

Dies funktioniert jedoch nicht, da der Filter zwei Parameter erwartet (IRepository und string []). Es ist natürlich auch nicht möglich, hier die Konstruktorinjektion zu verwenden.

Ich habe dann versucht, John Allers Lösung zu implementieren, die gefunden werden kann hier . Es sah vielversprechend aus, aber es gab mir diesen Fehler:

  

Eine Ausnahme vom Typ   'Microsoft.Practices.Unity.ResolutionFailedException' ist in aufgetreten   Microsoft.Practices.Unity.dll wurde aber nicht im Benutzercode behandelt

     

Zusätzliche Information: Auflösung der Abhängigkeit fehlgeschlagen, type =   "Fildela.ClaimsAuthorizeAccountAccess", name="(none)".

     

Ausnahme aufgetreten während: während der Auflösung.

     

Ausnahme ist: InvalidOperationException - Die Eigenschaft   _accountRepository vom Typ Findela.ClaimsAuthorizeAccountAccess ist nicht einstellbar.

     

Zum Zeitpunkt der Ausnahme war der Container:

     

Auflösen von Findela.ClaimsAuthorizeAccountAccess, (keine)

Irgendwelche Vorschläge, um diesen bösen Jungen zu lösen?

Danke!

    
Reft 26.08.2015, 20:01
quelle

3 Antworten

6

Installieren Sie zunächst das offizielle Paket Unity.Mvc anstelle von Unity.MVC4 . Dieses Paket installiert und registriert automatisch UnityFilterAttributeFilterProvider , das wir für die Abhängigkeitsinjektion des Attributs benötigen. Du kannst überprüfen, ob deine Unity gut konfiguriert ist, indem du App_Start & gt; UnityMvcActivator s Start Methode. Sie müssen folgende zwei Zeilen sehen:

%Vor%

Nun könnten Sie den öffentlichen Eigenschaften des Filters das Attribut [Dependency] hinzufügen.

%Vor%     
Sam Farajpour Ghamari 27.08.2015, 11:48
quelle
11

Wie in den Post Passiven Attributen beschrieben, ist die DI-freundliche Lösung die Trennung von AuthorizeAttribute in 2 Teile:

  1. Ein Attribut, das kein Verhalten zum Kennzeichnen Ihrer Controller und Aktionsmethoden enthält.
  2. Eine DI-freundliche Klasse, die IAuthorizationFilter implementiert und enthält das gewünschte Verhalten.

Für unsere Zwecke erben wir nur AuthorizeAttribute , um einige seiner eingebauten Funktionen zu nutzen.

Beachten Sie, dass es bei Verwendung dieses Ansatzes nicht sinnvoll ist, die Eigenschafteninjektion für Ihre Datenbankabhängigkeiten zu verwenden. Konstruktorinjektion ist sowieso immer eine bessere Wahl.

ClaimsIdentityAuthorizeAttribute

Zuerst haben wir unser Attribut, das kein Verhalten hat, um unsere Controller und Aktionen mit zu kennzeichnen. Wir fügen ein wenig Klugheit hinzu, um die Berechtigungen in einem Array zu analysieren, so dass dies nicht bei jeder Autorisierungsprüfung durchgeführt werden muss.

%Vor%

ClaimsIdentityAuthorizationFilter

Als nächstes haben wir unseren Autorisierungsfilter, der als globaler Filter fungiert.

Wir fügen ein WhiteListMode hinzu, das standardmäßig true ist, da dies die empfohlene Methode zur Konfiguration der Sicherheit ist (Controller und Aktionen erfordern eine Anmeldung, es sei denn, sie erhalten AllowAnonymousAttribute ). Glücklicherweise ist das Framework dafür in AuthorizeAttribute eingebaut, also verwenden wir es einfach als Flag, ob es global überprüft wird oder nicht.

Außerdem fügen wir einen Erweiterungspunkt hinzu, über den unser benutzerdefinierter Autorisierungsdienst eingespeist werden kann. Die 2 wahrscheinlichsten Dinge zu ändern sind:

  1. Der Test, um festzustellen, ob die Aktion autorisiert ist.
  2. Die Aktion, die ausgeführt werden soll, wenn der Benutzer nicht autorisiert ist.

Das sind die Dinge, die wir unserem Service hinzufügen. Sie können dies bei Bedarf in 2 separate Dienste umwandeln.

%Vor%

IAuthorizationService

%Vor%

ClaimsIdentityAuthorizationService

Also machen wir jetzt die erweiterte Anpassung, um Ansprüche zu unterstützen. Wir trennen das, so dass es eine Naht gibt, mit der wir eine andere Instanz injizieren können, wenn sich die Geschäftslogik in der Zukunft ändert.

%Vor%

Verwendung

Registrieren Sie Ihren Filter global und injizieren Sie seine Abhängigkeiten in Ihren Container.

%Vor%
  

HINWEIS: Wenn Sie möchten, dass eine der Abhängigkeiten des Filters eine kürzere Lebensdauer als Singleton hat, müssen Sie GlobalFilterProvider wie in diese Antwort .

Start

%Vor%

Bootstrapper

%Vor%

Und dann in Ihrem Controller, für die Sicherheit der schwarzen Liste, müssen Sie jede Aktion (oder Controller) dekorieren, um sie zu sperren.

%Vor%

Für die Sicherheit der weißen Liste müssen Sie nur die Aktionen dekorieren, auf die jeder mit AllowAnonymous Zugriff hat, oder eine ClaimsIdentityAuthorizeAttribute mit mehr oder weniger restriktiven Berechtigungen als die globale oder Controller-Ebene hinzufügen.

%Vor%     
NightOwl888 27.08.2015 16:26
quelle
6

Sie können keine Abhängigkeiten als Konstruktorparameter in Aktionsfilter einfügen, da sie als Attribute in C # implementiert sind. Sie müssen sie mit DependencyResolver.Current auflösen. Es ist eine Art Service Locator und es ist nicht cool, aber Sie haben wirklich keine Wahl. ASP.NET MVC verwendet den DI-Container nicht zum Erstellen von Aktionsfilterinstanzen.

%Vor%     
Ufuk Hacıoğulları 27.08.2015 10:39
quelle