Frage

Ich bin die Implementierung eines sicheren WCF-Dienst. Verwendung von Benutzername / Passwort oder Windows-Anmeldeinformationen Authentifizierung erfolgt. Der Dienst wird in einem Windows-Service-Prozess gehostet. Nun, ich versuche, den besten Weg, um herauszufinden, zu implementieren Genehmigung für jeden Service-Betrieb.

Betrachten wir zum Beispiel die folgende Methode:

public EntityInfo GetEntityInfo(string entityId);

Wie Sie vielleicht wissen, in WCF, gibt es eine Operation Objekt, von dem Sie die Anmeldeinformationen abrufen können vom Anrufer / Client übergeben. Nun, Authentifizierung hätte bereits durch die Zeit, die erste Zeile in der Methode beendet wird aufgerufen. Doch wie setzen wir Zulassung, wenn die Entscheidung über die Eingangsdaten selbst abhängt? Zum Beispiel in dem obigen Fall, sagen ‚admin‘ Benutzer (deren Berechtigungen usw. werden in einer Datenbank gespeichert ist), dürfen Unternehmen Informationen und andere Benutzer sollten nicht erlaubt sein ... wo tun wir setzen die Berechtigungsprüfungen bekommen?

Sagen wir es in der ersten Zeile des Verfahrens stellten etwa so:

CheckAccessPermission(PermissionType.GetEntity, user, entityId) //user is pulled from the current OperationContext

Nun, es gibt ein paar Fragen:

  1. Haben wir die EntityID (zB Scheck null / leer Wert usw.) vor der Berechtigungsprüfung oder in der Berechtigungsprüfung validieren? Mit anderen Worten, sollten, wenn Berechtigungsprüfungen in jedem Verfahren einbezogen werden, ist das ein gutes Muster? passieren soll, die zuerst - Argument Validierung oder Genehmigung

  2. Wie wir Unit-Test ein WCF-Dienst, wenn Berechtigungsprüfungen alle über den Ort wie diese sind, und wir keine Operation in der Unit-Test haben !? (Vorausgesetzt, ich versuche diese Serviceklasse zu testen Implementierung direkt ohne irgendwelche des WCF-Setup).

Irgendwelche Ideen Jungs?

War es hilfreich?

Lösung

Frage 1, tut absolut Genehmigung zuerst. Kein Code (in Ihrer Kontrolle) soll ausgeführt werden, bevor die Genehmigung engster Sicherheit aufrechtzuerhalten. Paul Beispiel oben ist ausgezeichnet.

Frage 2, könnten Sie damit umgehen, indem Sie Ihre konkrete Service-Implementierung Subklassen. Machen Sie die wahre Business-Logik Implementierung eine abstrakte Klasse mit einer abstrakten „CheckPermissions“ Methode, wie Sie oben erwähnt. Dann erstellen Sie zwei Unterklassen, eine für WCF Verwendung, und eine (sehr isoliert in einem nicht entfalteten DLL), die true zurückgibt (oder was auch immer Sie möchten, dass es in Ihrer Unit-Tests tun).

Beispiel (beachten Sie, diese sollten allerdings nicht in der gleichen Datei oder auch DLL sein!):

public abstract class MyServiceImpl
{
    public void MyMethod(string entityId)
    {
        CheckPermissions(entityId);
        //move along...
    }
    protected abstract bool CheckPermissions(string entityId);
}

public class MyServiceUnitTest
{
    private bool CheckPermissions(string entityId)
    {
        return true;
    }
}

public class MyServiceMyAuth
{
    private bool CheckPermissions(string entityId)
    {
        //do some custom authentication
        return true;
    }
}

Dann ist Ihre WCF-Bereitstellung verwendet die Klasse „MyServiceMyAuth“, und Sie tun, um Ihre Unit-Tests gegen die andere.

Andere Tipps

Frage 1 ist es am besten Genehmigung zuerst durchzuführen. Auf diese Weise, die Sie nicht Validierung Fehlermeldungen zurück an nicht autorisierte Benutzer auslaufen.

BTW, anstelle eine home-grown-Authentifizierungsmethode verwenden (was ich davon ausgehen, ist das, was Ihr CheckAccessPermission ist), können Sie in der Lage sein, Haken bis zu WCF out-of-the-box-Unterstützung für ASP.NET Rollenanbieter. Sobald dies geschehen ist, führen Sie die Berechtigung über OperationContext.Current.ServiceSecurityContext.PrimaryIdentity.IsInRole (). Die PrimaryIdentity ist ein IPrincipal.

Über Frage # 2, würde ich dies mit Dependency Injection tun und Ihre Service-Implementierung in etwa so ein:

class MyService : IMyService
{
    public MyService() : this(new UserAuthorization()) { }
    public MyService(IAuthorization auth) { _auth = auth; }

    private IAuthorization _auth;

    public EntityInfo GetEntityInfo(string entityId)
    {
            _auth.CheckAccessPermission(PermissionType.GetEntity, 
                    user, entityId);

            //Get the entity info
    }
}

Beachten Sie, dass IAuthorization ist eine Schnittstelle, die Sie definieren würde.

Da Sie gehen, um den Service-Typ Prüfung werden direkt (das heißt, ohne es in dem WCF-Hosting-Rahmen ausgeführt wird) Sie einfach Ihren Dienst einrichten einen Dummy IAuthorization Typen zu verwenden, der alle Anrufe ermöglicht. Allerdings ist ein noch besserer Test, um die IAuthorization und testet, um zu spotten, dass sie genannt wird, wann und mit den Parametern, die Sie erwarten. Auf diese Weise können Sie testen, dass Ihre Anrufe an die Autorisierungsmethoden gültig sind, zusammen mit der Methode selbst.

die Zulassung in seiner eigenen Art Trennung ermöglicht auch leichter Sie zu testen, dass es in Isolation korrekt ist. In meiner (wenn auch begrenzten) Erfahrung mit DI „Muster“ gibt Ihnen wesentlich bessere Trennung von Bedenken und Testbarkeit in Ihren Typen sowie zu einer saubereren Schnittstelle führt (dies Debatte offensichtlich offen ist).

Meine bevorzugte Mockframework ist RhinoMocks , die frei ist und hat sehr schöne fließend Schnittstelle aber es gibt viele andere da draußen. Wenn Sie mehr über DI hier wissen möchten sind einige gute Primer und .Net-Frameworks:

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top