Laden...

Fein justierbare Authentifizierung in WCF??

Erstellt von Fracoon vor 15 Jahren Letzter Beitrag vor 15 Jahren 1.391 Views
F
Fracoon Themenstarter:in
85 Beiträge seit 2007
vor 15 Jahren
Fein justierbare Authentifizierung in WCF??

Hi@all,

ich möchte gerne eine Serveranwendung schreiben die WCF benutzt um mit den Clients zu kommunizieren.

Das nur in Windows bekannte Benutzer zugriff auf den Service-Host haben ist mir bereits gelungen. Ist auch so gewollt.

Jetzt hätte ich aber gerne eine feinere Kontrolle darüber welcher User was machen darf.

Das ganze sollte auf Methodenebene einstelbar sein.

So ist die Lösung die ich mir ausgedacht habe :


class Test : ITest
    {
        #region ITest Members
        
        public Boolean logtest(string bla)
        {
            string username;
            Permissions s = Permissions.getInstance();
            username = ServiceSecurityContext.Current.WindowsIdentity.Name;

            if (!s.Users[username].Contains(permissions.call_logtest)
            {
                //TODO : Zugriffsverweigerung an Client melden, Methode beenden (Mit Exception??)
            }

            return true;
            
        }

        #endregion
    }

Innerhalb des Methodenaufrufs im Service wird also überprüft ob der User berechtigt ist die Methode testlog aufzurufen (permissions.call_logtest)

Somit könnte ich wirklich auf Methodenebene steuern ob ein User berechtigt ist oder nicht.

Was ich nicht schön an dieser Lösung finde ist, dass der Benutzer wirklich bei jedem aufruf von logtest überprüft wird.

Gibts ne schönere Lösung?

3.728 Beiträge seit 2005
vor 15 Jahren
Ticket

Hallo Fracoon,

Du könntest z.B. einen Sicherheitsdienst schreiben, der den Benutzer authentifiziert und ihm dann ein Ticket ausstellt. Dieses Ticket ist dann z.B. 5 Minuten gültig. Wenn der Client beim Dienst das Ticket "vorzeigt" weiss der Dienst sofort, ob der Benutzer korrekt authentifiziert ist, oder nicht. Wenn das Ticket abgelaufen ist, versucht der Sicherheitsdienst es zu erneuern indem er die Sicherheitsprüfung erneut durchführt. Wenn der Benutzer erneut korrekt authentifiziert wurde, wird die Lease des Tickets verlängert, ansonsten wird das Ticket verworfen und der Client bekommt keinen Zugriff. Die aufwändigen Sicherheitsprüfungen werden also nur beim ersten Zugriff und jeweils dann gemacht, wenn das Ticket abläuft. Ein Hacker hat also nur solange Zeit die Anwendung zu hacken, wie die Gültigkeitsdauer des Sitzungstickets ist. Im Gegenzug wird die Last der Sicherheitsprüfungen erheblich reduziert.

Natürlich möchtest Du, nicht in jede Dienst-Methode einen Ticket-Parameter einbauen. Das Sicherheitssystem soll unsichtbar im Hintergrund arbeiten und sich nur mit Faults bzw. Exceptions bemerkbar machen, wenn was faul ist.

Genau sowas habe ich in meinem Architekturbeispiel hier implementiert: .NET Applikationsserver

In meinem Fall habe ich Remoting als Kommunikationstechnologie eingesetzt. Mit WCF geht das aber auch. Statt das Sitzungsticket in den CallContext zu hängen, musst Du ein Bevahior für Deinen Service schreiben, welcher das Ticket als Header an den WCF-OperationContext heftet. Mit den MSDN-Beispielen und ein bischen Recherche im Web, sollte das ohne größere Probleme zu machen sein.

F
Fracoon Themenstarter:in
85 Beiträge seit 2007
vor 15 Jahren

Hallo Rainbird,

vielen Dank für deine Antwort. Ich habe mir deinen Applikationsserver mal angesehen. Kann aber nicht ganz verstehen wo der Vorteil gegenüber meiner Lösung sein soll.

Machst du nicht an dieser stelle "genau" das selbe wie ich?


// Wenn der Aufrufer in der Rolle "Product Reader" ist ...
if (ApplicationServer.IsInRole("Product Reader";))
{
// Aufruf an Geschäftslogik delegieren
return new ProductManager().GetProduct(productID);
}

Um nochmal kurz meine Situation zu beschreiben (vieleicht war es etwas unklar) :

Hier ist der Auszug von dem ich denke, dass er dem Ansatz von dir sehr Ähnlich ist


string username;
Permissions s = Permissions.getInstance();
username = ServiceSecurityContext.Current.WindowsIdentity.Name;

if (!s.Users[username].Contains(permissions.call_logtest)
{
//TODO : Zugriffsverweigerung an Client melden, Methode beenden (Mit Exception??)
}

"Permissions" ist ein Singleton, welcher ein Dictionary enthält. In diesem Dictionary steht der Benutzername (String) als Key und eine List von Rechten (Gebildet aus einem ENUM).
Um den Dienst überhaupt nutzen zu können, muss der Clientuser auf dem Rechner auf dem der Server läuft angelegt sein.

Kannst du mir bitte erklären wo der Vorteil des von dir genannten Tickets besteht? Ich steig nicht dahinter, weil es für mich so aussieht als würdest du (genau wie ich) in jeder Methode des Dienstes eine Gruppenzugehörigkeit abfragen).

3.728 Beiträge seit 2005
vor 15 Jahren
Authentifizierung und Rechteprüfung

Hallo Fracoon,

das Ticket zeigt nur an, dass sich der Benutzer korrekt am Applikationsserver angemeldet hat und dort über eine gültige Sitzung verfügt. Ohne Ticket müsste die Identitätsprüfung des Benutzers (also nur wer er ist und nicht, in welchen Vereinen er Mitglied ist) bei jedem Funktionsaufruf durchgeführt werden. Hinzu kommt, dass die Identität des Aufrufers bei einer Aufrufkette über mehrere Dienste (Also Dienst A konsumiert intern Dienst B) nicht weitergegeben wird (Der Aufruf von Dienst B würde im Kontext des AppServer-Dienstkontos laufen). Also wird ein Ticket benötigt, welches man an den Aufrufkontext hängt. Der Sicherheitsdienst zieht dann die gespeicherte Benutzeridentiät der Sitzung heran (welche er anhand der Ticketkennung ermittelt) Bei mehreren Hops hätte der Sicherheitsdienst arge Probleme, den ursprünglichen Client-Benutzer herauszufinden. Bei mehreren Applikationsservern könnte man die Sitzungsliste auf replizieren. Das Ticket ist also nur für die Authentifizierung nützlich, aber nur indirekt für die eigentliche Rechteprüfung.

Die Rechteprüfung kommt aber erst dann überhaupt zum Einsatz, wenn ein Benutzer sich erfolgreich angemeldet hat. Benutzer ohne gültige Sitzung haben von vorn herein keine Rechte.

Um eine rollenbasierte Sicherheit zu haben, muss die nötige Rolle natürlich bei jedem Funktionsaufruf geprüft werden. Ich hatte auch schon überlegt, das Ergebnis der Rollenprüfung zu cachen. Da Windows das aber bereits für mich tut, habe ich es sein lassen und mache den Aufruf jedesmal direkt. Die Prüfung auf Zugehörigkeit zu einer Windows-Gruppe ist sehr schnell. Die Ressourcenbelastung hält sich auch in Grenzen. Da der Benutzer den Großteil der Zeit eh nur vor der GUI sitzt und diese anstarrt und im schlimmsten Fall alle paar Sekunden was übertragen werden muss, kann man das in Kauf nehmen. Oder hast Du bei Dir starke Leistungseinbußen gemessen?

F
Fracoon Themenstarter:in
85 Beiträge seit 2007
vor 15 Jahren

Vielen dank für die Zeit die du dir nimmst Rainbird...

Irgendwie habe ich das Gefühl wir reden aneinander vorbei.

Ich wollte wissen ob es eine bessere Möglichkeit gibt PRO METHODE Sicherheitsrichtlinien zu implementieren. Aus deinem ersten Posting entnehme ich, dass du denkst dass es über ein Ticket besser gelöst werden kann.

Ich vermute aber folgendes : Das verhalten was bei dir durch das Ticket erreicht wird, macht bei mir der WCF Service von ganz alleine. Ich habe ihn so konfiguriert, dass nur Benutzer die es auch in Windows gibt eine Session aufbauen können.

Die Rechteprüfung kommt aber erst dann überhaupt zum Einsatz, wenn ein Benutzer sich erfolgreich angemeldet hat. Benutzer ohne gültige Sitzung haben von vorn herein keine Rechte.

Bei mir : Wer nicht über ein gültiges Windows Konto verfügt hat von vorn herein keine Rechte.

Um eine rollenbasierte Sicherheit zu haben, muss die nötige Rolle natürlich bei jedem Funktionsaufruf geprüft werden

Genau das tue ich. Unabhängig von der Windows Gruppe in der sich jemand befindet. Die Berechtigungsprüfung findet über meinen Permissions Singleton statt.

Hinzu kommt, dass die Identität des Aufrufers bei einer Aufrufkette über mehrere Dienste (Also Dienst A konsumiert intern Dienst B) nicht weitergegeben wird (Der Aufruf von Dienst B würde im Kontext des AppServer-Dienstkontos laufen). Also wird ein Ticket benötigt, welches man an den Aufrufkontext hängt. Der Sicherheitsdienst zieht dann die gespeicherte Benutzeridentiät der Sitzung heran (welche er anhand der Ticketkennung ermittelt) Bei mehreren Hops hätte der Sicherheitsdienst arge Probleme, den ursprünglichen Client-Benutzer herauszufinden. Bei mehreren Applikationsservern könnte man die Sitzungsliste auf replizieren. Das Ticket ist also nur für die Authentifizierung nützlich, aber nur indirekt für die eigentliche Rechteprüfung.

Darüber habe ich mir noch keine Gedanken gemacht. Könnte mir aber vorstellen das WCF da auch eine Integrierte Lösung bereithällt.

Ich würde also sagen das unser Ansatz sehr ähnlich ist. Dein Ansatz ist nur etwas vorausschauender?!?!?!?

3.728 Beiträge seit 2005
vor 15 Jahren
Ansätze

Hallo Fracoon,

Du hast Recht, ein Ticketsystem bringt für Deine konkrete Frage nicht wirklich was.
Meine Rollenprüfung muss auch bei jedem Funktionsaufruf durchgeführt werden. Bei statuslosen Geschäftsdiensten kann ich mir aber auch nicht vorstellen, wie man das anders machen sollte.

Das Problem mit Diensten, die andere Dienste konsumieren, besteht aber auch bei WCF. Sessions sind in WCF nicht dienstübergreifend, wie z.B. in ASP.NET. Ob man die Dienste der eigenen Anwendung in Schichten aufteilen kann/muss, kommt auf die Anwendung an. Ich wäre allerdings bereits bei meinem kleinen Architekturbeispiel schon nicht ohne ausgekommen.