Sehr häufig sollen nicht alle Anwender eines Systems berechtigt sein alle, durch SignalR-Hubs bereitgestellten Funktionen zu nutzen. Im Folgenden wird gezeigt, wie man eine Benutzeranmeldung mit Username und Password für einen SignalR-Hub selbst implementieren kann.
Das AuthorizeAttribute
Die AuthorizeAttribute Klasse ist Bestandteil von SignalR und dient dazu Zugriffe auf einen Hub einzuschränken. Da sie von der Attribute-Klasse erbt, kann man ihre Objekte wie ein „Tag“ an andere Klassen (z.B. einen SignalR-Hub) „anheften“. SignalR verwendet dieses AuthorizeAttribute-Objekt dann um herauszufingen, ob ein Zugriff auf den Hub berechtigt ist, oder nicht.
Wir erstellen nun eine neue Klasse namens HubAuthorizationAttribute, welche von AuthorizeAttribute erbt, und implementieren darin unsere Funktionen zur Passwort-Überprüfung. Anschließend werden wir ein Objekt dieser Klasse als Attribut an einen SignalR-Hub anheften.
using Microsoft.AspNet.SignalR; using Microsoft.AspNet.SignalR.Hubs; public class HubAuthorizationAttribute : AuthorizeAttribute { public override bool AuthorizeHubConnection(HubDescriptor hubDescriptor, IRequest request) { string user = request.Headers["X-User"]; string passwd = request.Headers["X-PW"]; // Hier prüfen, ob user und passwd gültig sind! // Wenn der Zugriff erlaubt ist, true zurückgeben. Andernfalls false. return true; // In diesem Fall: Zugriff erlaubt. } public override bool AuthorizeHubMethodInvocation(IHubIncomingInvokerContext hubIncomingInvokerContext, bool appliesToMethod) { return true; } }
Die Methode AuthorizeHubConnection wird immer aufgerufen, wenn ein Client sich mit einem Hub verbinden möchte. Gibt diese Methode ein true zurück, ist die Verbindung erlaubt. Gibt die Methode dagegen ein false zurück, wird die Verbindung abgewiesen. Im obigen Beispiel-Code gehen wir davon aus, dass der Client seinen Nutzernamen und Password in die Felder X-User und X-PW des Http-Headers der Anfrage geschrieben hat. Da wir beim Aufruf von AuthorizeConnection den Http-Request als Parameter übergeben bekommen, haben wir Zugriff auf diese Felder. Im Beispiel oben kopieren wir den Nutzernamen und das Password in die String-Variablen user und passwd. Wir können uns nun z.B. mit einer Benutzerdatenbank verbinden und prüfen, ob die Login-Daten gültig sind. Im Beispiel oben haben wir diesen Schritt einfach ausgelassen und geben immer ein true zurück, denn es soll hier lediglich das Prinzip erklärt werden.
Einen SignalR-Hub absichern
Wir können nun einen SignalR-Hub absichern, indem wir unser neues Attribut HubAuthorization an den Hub anheften, d.h. wir schreiben es in eckigen Klammern vor die Hub-Klasse (hier: ExampleHub):
using Microsoft.AspNet.SignalR; using Microsoft.AspNet.SignalR.Hubs; namespace MyWebApplication { [HubAuthorization] [HubName("ExampleHub")] public class ExampleHub : Hub { public ExampleHub() { } public int Add(int a, int b) { return a+b; } } }
Immer wenn nun eine Verbindung zu diesem Hub hergestellt werden soll, wird diese von dem HubAuthorizationAttribute geprüft und ggf. abgelehnt.
User und Password durch einen C# Client übermitteln
Das folgende Beispiel zeigt, wie die Felder X-User und X-PW in einem C# Client in den Http-Header eingetragen werden können:
var hubConnection = new HubConnection("http://localhost:57256/"); var proxy = hubConnection.CreateHubProxy("ExampleHub"); hubConnection.Headers["X-User"] = "Beispielnutzer"; hubConnection.Headers["X-PW"] = "geheim"; hubConnection.Start().Wait(); Console.WriteLine(proxy.Invoke<int>("Add", new object[] { 2,3} ).Result); // Ergebnis: 5