Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
von Patrick Fletcher, Tom FitzMacken
Warnung
Diese Dokumentation ist nicht für die neueste Version von SignalR vorgesehen. Sehen Sie sich ASP.NET Core SignalR an.
In diesem Thema wird beschrieben, wie Sie einschränken, welche Benutzer oder Rollen auf Hubmethoden zugreifen können.
Überblick
Dieses Thema enthält die folgenden Abschnitte:
Autorisieren des Attributs
SignalR stellt das Authorize-Attribut bereit, um anzugeben, welche Benutzer oder Rollen Zugriff auf einen Hub oder eine Methode haben. Dieses Attribut befindet sich im Microsoft.AspNet.SignalR Namespace. Sie wenden das Authorize Attribut entweder auf einen Hub oder bestimmte Methoden in einem Hub an. Wenn Sie das Authorize Attribut auf eine Hubklasse anwenden, wird die angegebene Autorisierungsanforderung auf alle Methoden im Hub angewendet. Die verschiedenen Arten von Autorisierungsanforderungen, die Sie anwenden können, finden Sie unten. Ohne das Authorize Attribut sind alle öffentlichen Methoden auf dem Hub für einen Client verfügbar, der mit dem Hub verbunden ist.
Wenn Sie eine Rolle namens "Admin" in Ihrer Webanwendung definiert haben, können Sie angeben, dass nur Benutzer in dieser Rolle mit dem folgenden Code auf einen Hub zugreifen können.
[Authorize(Roles = "Admin")]
public class AdminAuthHub : Hub
{
}
Oder Sie können angeben, dass ein Hub eine Methode enthält, die für alle Benutzer verfügbar ist, und eine zweite Methode, die nur authentifizierten Benutzern zur Verfügung steht, wie unten dargestellt.
public class SampleHub : Hub
{
public void UnrestrictedSend(string message){ . . . }
[Authorize]
public void AuthenticatedSend(string message){ . . . }
}
In den folgenden Beispielen werden verschiedene Autorisierungsszenarien behandelt:
[Authorize]– nur authentifizierte Benutzer[Authorize(Roles = "Admin,Manager")]– nur authentifizierte Benutzer in den angegebenen Rollen[Authorize(Users = "user1,user2")]– nur authentifizierte Benutzer mit den angegebenen Benutzernamen[Authorize(RequireOutgoing=false)]– Nur authentifizierte Benutzer können den Hub aufrufen, aber Anrufe vom Server zurück an Clients sind nicht durch Autorisierung beschränkt, z. B. wenn nur bestimmte Benutzer eine Nachricht senden können, aber alle anderen Personen die Nachricht empfangen können. Die RequireOutgoing-Eigenschaft kann nur auf den gesamten Hub angewendet werden, nicht auf Einzelne Methoden innerhalb des Hubs. Wenn "RequireOutgoing" nicht auf "false" festgelegt ist, werden nur Benutzer, die die Autorisierungsanforderung erfüllen, vom Server aufgerufen.
Authentifizierung für alle Hubs erforderlich
Sie können eine Authentifizierung für alle Hubs und Hubmethoden in Ihrer Anwendung anfordern, indem Sie die RequireAuthentication-Methode aufrufen, wenn die Anwendung gestartet wird. Sie können diese Methode verwenden, wenn Sie über mehrere Hubs verfügen und eine Authentifizierungsanforderung für alle erzwingen möchten. Mit dieser Methode können Sie keine Rollen-, Benutzer- oder ausgehende Autorisierung angeben. Sie können nur angeben, dass der Zugriff auf die Hubmethoden auf authentifizierte Benutzer beschränkt ist. Sie können das Authorize-Attribut jedoch weiterhin auf Hubs oder Methoden anwenden, um zusätzliche Anforderungen anzugeben. Jede Anforderung, die Sie in Attributen angeben, wird zusätzlich zur grundlegenden Authentifizierungsanforderung angewendet.
Das folgende Beispiel zeigt eine Datei "Global.asax", die alle Hubmethoden auf authentifizierte Benutzer beschränkt.
public class Global : HttpApplication
{
void Application_Start(object sender, EventArgs e)
{
RouteTable.Routes.MapHubs();
GlobalHost.HubPipeline.RequireAuthentication();
}
}
Wenn Sie die RequireAuthentication() Methode aufrufen, nachdem eine SignalR-Anforderung verarbeitet wurde, löst SignalR eine InvalidOperationException Ausnahme aus. Diese Ausnahme wird ausgelöst, da Sie der HubPipeline kein Modul hinzufügen können, nachdem die Pipeline aufgerufen wurde. Im vorherigen Beispiel wird gezeigt, wie die RequireAuthentication Methode in der Application_Start Methode aufgerufen wird, die vor der Behandlung der ersten Anforderung einmal ausgeführt wird.
Angepasste Autorisierung
Wenn Sie anpassen müssen, wie die Autorisierung bestimmt wird, können Sie eine Klasse erstellen, die von AuthorizeAttribute abgeleitet ist, und die UserAuthorized-Methode überschreiben. Diese Methode wird für jede Anforderung aufgerufen, um zu bestimmen, ob der Benutzer berechtigt ist, die Anforderung abzuschließen. In der überschriebenen Methode stellen Sie die notwendige Logik für Ihr Autorisierungsszenario bereit. Das folgende Beispiel zeigt, wie Sie die Autorisierung durch anspruchsbasierte Identität erzwingen.
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
public class AuthorizeClaimsAttribute : AuthorizeAttribute
{
protected override bool UserAuthorized(System.Security.Principal.IPrincipal user)
{
if (user == null)
{
throw new ArgumentNullException("user");
}
var principal = (ClaimsPrincipal)user;
if (principal != null)
{
Claim authenticated = principal.FindFirst(ClaimTypes.Authentication);
return authenticated.Value == "true" ? true : false;
}
else
{
return false;
}
}
}
Übergeben von Authentifizierungsinformationen an Clients
Möglicherweise müssen Sie Authentifizierungsinformationen im Code verwenden, der auf dem Client ausgeführt wird. Sie übergeben die erforderlichen Informationen beim Aufrufen der Methoden auf dem Client. Eine Chatanwendungsmethode könnte z. B. als Parameter den Benutzernamen der Person übergeben, die eine Nachricht veröffentlicht, wie unten dargestellt.
public Task SendChatMessage(string message)
{
string name;
var user = Context.User;
if (user.Identity.IsAuthenticated)
{
name = user.Identity.Name;
}
else
{
name = "anonymous";
}
return Clients.All.addMessageToPage(name, message);
}
Oder Sie können ein Objekt erstellen, um die Authentifizierungsinformationen darzustellen und dieses Objekt als Parameter zu übergeben, wie unten dargestellt.
public class SampleHub : Hub
{
public override Task OnConnected()
{
return Clients.All.joined(GetAuthInfo());
}
protected object GetAuthInfo()
{
var user = Context.User;
return new
{
IsAuthenticated = user.Identity.IsAuthenticated,
IsAdmin = user.IsInRole("Admin"),
UserName = user.Identity.Name
};
}
}
Sie sollten niemals die Verbindungs-ID eines Clients an andere Clients übergeben, da ein böswilliger Benutzer es verwenden könnte, um eine Anforderung von diesem Client nachzuahmen.
Authentifizierungsoptionen für .NET-Clients
Wenn Sie über einen .NET-Client verfügen, z. B. eine Konsolen-App, die mit einem Hub interagiert, der auf authentifizierte Benutzer beschränkt ist, können Sie die Authentifizierungsanmeldeinformationen in einem Cookie, dem Verbindungsheader oder einem Zertifikat übergeben. In den Beispielen in diesem Abschnitt wird gezeigt, wie Sie diese verschiedenen Methoden zum Authentifizieren eines Benutzers verwenden. Sie sind keine voll funktionsfähigen SignalR-Apps. Weitere Informationen zu .NET-Clients mit SignalR finden Sie im Leitfaden zur Hubs-API – .NET Client.
Keks
Wenn Ihr .NET-Client mit einem Hub interagiert, der ASP.NET Formularauthentifizierung verwendet, müssen Sie das Authentifizierungscookies manuell für die Verbindung festlegen. Sie fügen das Cookie zur CookieContainer Eigenschaft des HubConnection-Objekts hinzu. Das folgende Beispiel zeigt eine Konsolen-App, die ein Authentifizierungscookies von einer Webseite abruft und dieses Cookie der Verbindung hinzufügt. Die URL https://www.contoso.com/RemoteLogin im Beispiel verweist auf eine Webseite, die Sie erstellen müssen. Die Seite würde den geposteten Benutzernamen und das Kennwort abrufen und versuchen, sich mit den Anmeldeinformationen beim Benutzer anzumelden.
class Program
{
static void Main(string[] args)
{
var connection = new HubConnection("http://www.contoso.com/");
Cookie returnedCookie;
Console.Write("Enter user name: ");
string username = Console.ReadLine();
Console.Write("Enter password: ");
string password = Console.ReadLine();
var authResult = AuthenticateUser(username, password, out returnedCookie);
if (authResult)
{
connection.CookieContainer = new CookieContainer();
connection.CookieContainer.Add(returnedCookie);
Console.WriteLine("Welcome " + username);
}
else
{
Console.WriteLine("Login failed");
}
}
private static bool AuthenticateUser(string user, string password, out Cookie authCookie)
{
var request = WebRequest.Create("https://www.contoso.com/RemoteLogin") as HttpWebRequest;
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.CookieContainer = new CookieContainer();
var authCredentials = "UserName=" + user + "&Password=" + password;
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(authCredentials);
request.ContentLength = bytes.Length;
using (var requestStream = request.GetRequestStream())
{
requestStream.Write(bytes, 0, bytes.Length);
}
using (var response = request.GetResponse() as HttpWebResponse)
{
authCookie = response.Cookies[FormsAuthentication.FormsCookieName];
}
if (authCookie != null)
{
return true;
}
else
{
return false;
}
}
}
Die App auf der Konsole postet die Anmeldeinformationen an www.contoso.com/RemoteLogin, was auf eine leere Seite verweisen könnte, die die folgende Code-Behind-Datei enthält.
using System;
using System.Web.Security;
namespace SignalRWithConsoleChat
{
public partial class RemoteLogin : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string username = Request["UserName"];
string password = Request["Password"];
bool result = Membership.ValidateUser(username, password);
if (result)
{
FormsAuthentication.SetAuthCookie(username, false);
}
}
}
}
Windows-Authentifizierung
Bei Verwendung der Windows-Authentifizierung können Sie die Anmeldeinformationen des aktuellen Benutzers mithilfe der DefaultCredentials-Eigenschaft übergeben. Sie legen die Anmeldeinformationen für die Verbindung auf den Wert der Datei DefaultCredentials fest.
class Program
{
static void Main(string[] args)
{
var connection = new HubConnection("http://www.contoso.com/");
connection.Credentials = CredentialCache.DefaultCredentials;
connection.Start().Wait();
}
}
Header der Verbindung
Wenn Ihre Anwendung keine Cookies verwendet, können Sie Benutzerinformationen im Verbindungsheader weitergeben. Sie können z. B. ein Token im Verbindungsheader übergeben.
class Program
{
static void Main(string[] args)
{
var connection = new HubConnection("http://www.contoso.com/");
connection.Headers.Add("myauthtoken", /* token data */);
connection.Start().Wait();
}
}
Anschließend würden Sie im Hub das Token des Benutzers überprüfen.
Zertifikat
Sie können ein Clientzertifikat übergeben, um den Benutzer zu überprüfen. Sie fügen das Zertifikat beim Erstellen der Verbindung hinzu. Das folgende Beispiel zeigt nur, wie der Verbindung ein Clientzertifikat hinzugefügt wird. die vollständige Konsolen-App wird nicht angezeigt. Es verwendet die X509Certificate-Klasse , die verschiedene Möglichkeiten zum Erstellen des Zertifikats bietet.
class Program
{
static void Main(string[] args)
{
var connection = new HubConnection("http://www.contoso.com/");
connection.AddClientCertificate(X509Certificate.CreateFromCertFile("MyCert.cer"));
connection.Start().Wait();
}
}