Ověřování a autorizace center SignalR

Patrick Fletcher, Tom FitzMacken

Upozornění

Tato dokumentace není určená pro nejnovější verzi SignalR. Podívejte se na ASP.NET Core SignalR.

Toto téma popisuje, jak omezit, kteří uživatelé nebo role mají přístup k metodám centra.

Verze softwaru použité v tomto tématu

Předchozí verze tohoto tématu

Informace o starších verzích služby SignalR najdete v tématu Starší verze služby SignalR.

Dotazy a komentáře

Pošlete nám prosím zpětnou vazbu k tomu, jak se vám tento kurz líbil a co bychom mohli vylepšit v komentářích v dolní části stránky. Pokud máte dotazy, které přímo nesouvisejí s kurzem, můžete je publikovat na fóru ASP.NET SignalR nebo StackOverflow.com.

Přehled

Toto téma obsahuje následující oddíly:

Atribut Authorize

SignalR poskytuje atribut Autorizovat , který určuje, kteří uživatelé nebo role mají přístup k centru nebo metodě. Tento atribut se nachází v Microsoft.AspNet.SignalR oboru názvů. Atribut použijete Authorize na rozbočovač nebo konkrétní metody v centru. Když použijete Authorize atribut na třídu centra, zadaný požadavek na autorizaci se použije na všechny metody v centru. Toto téma obsahuje příklady různých typů požadavků na autorizaci, které můžete použít. Bez atributu Authorize má připojený klient přístup k jakékoli veřejné metodě v centru.

Pokud jste ve webové aplikaci definovali roli s názvem "Správa", můžete určit, aby k centru měli přístup jenom uživatelé v této roli pomocí následujícího kódu.

[Authorize(Roles = "Admin")] 
public class AdminAuthHub : Hub 
{ 
}

Nebo můžete určit, že centrum obsahuje jednu metodu, která je k dispozici všem uživatelům, a druhou metodu, která je k dispozici pouze ověřeným uživatelům, jak je znázorněno níže.

public class SampleHub : Hub 
{ 
    public void UnrestrictedSend(string message){ . . . } 

    [Authorize] 
    public void AuthenticatedSend(string message){ . . . } 
}

Následující příklady řeší různé scénáře autorizace:

  • [Authorize] – pouze ověření uživatelé
  • [Authorize(Roles = "Admin,Manager")] – pouze ověření uživatelé v zadaných rolích
  • [Authorize(Users = "user1,user2")] – pouze ověření uživatelé se zadanými uživatelskými jmény
  • [Authorize(RequireOutgoing=false)] – Centrum můžou vyvolat jenom ověření uživatelé, ale volání ze serveru zpět na klienty nejsou omezena autorizací, například když zprávu můžou odeslat jenom někteří uživatelé, ale všichni ostatní můžou zprávu přijmout. Vlastnost RequireOutgoing lze použít pouze na celé centrum, nikoli na metody jednotlivců v rámci centra. Pokud možnost RequireOutgoing není nastavená na hodnotu false, budou ze serveru volána pouze uživatelé, kteří splňují požadavky na autorizaci.

Vyžadovat ověřování pro všechna centra

Při spuštění aplikace můžete vyžadovat ověřování pro všechna centra a metody centra voláním metody RequireAuthentication . Tuto metodu můžete použít, když máte více center a chcete vynutit požadavek na ověřování pro všechna z nich. Při použití této metody nelze zadat požadavky na autorizaci role, uživatele nebo odchozí autorizaci. Můžete pouze určit, že přístup k metodám centra je omezený na ověřené uživatele. I tak ale můžete použít atribut Authorize na rozbočovače nebo metody a zadat další požadavky. Každý požadavek, který zadáte v atributu, se přidá do základního požadavku ověřování.

Následující příklad ukazuje spouštěcí soubor, který omezuje všechny metody centra na ověřené uživatele.

public partial class Startup {
    public void Configuration(IAppBuilder app) {
        app.MapSignalR();
        GlobalHost.HubPipeline.RequireAuthentication();
    }
}

Pokud zavoláte metodu RequireAuthentication() po zpracování požadavku SignalR, SignalR vyvolá InvalidOperationException výjimku. SignalR vyvolá tuto výjimku, protože po vyvolání kanálu nelze přidat modul do HubPipeline. Předchozí příklad ukazuje volání RequireAuthentication metody v Configuration metodě, která se provede jednou před zpracováním prvního požadavku.

Přizpůsobená autorizace

Pokud potřebujete přizpůsobit způsob určení autorizace, můžete vytvořit třídu, která se odvozuje z AuthorizeAttribute metody UserAuthorized a přepisuje ji. Pro každý požadavek SignalR vyvolá tuto metodu, aby určil, jestli má uživatel oprávnění k dokončení požadavku. V přepsáné metodě zadáte logiku potřebnou pro váš scénář autorizace. Následující příklad ukazuje, jak vynutit autorizaci prostřednictvím identity založené na deklaracích.

[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 = user as ClaimsPrincipal;

        if (principal != null)
        {
            Claim authenticated = principal.FindFirst(ClaimTypes.Authentication);
            if (authenticated != null && authenticated.Value == "true")
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        else
        {
            return false;
        }
    }
}

Předávání ověřovacích informací klientům

Možná budete muset použít ověřovací informace v kódu, který běží na klientovi. Při volání metod v klientovi předáte požadované informace. Metoda chatovací aplikace může například předat jako parametr uživatelské jméno osoby, která zprávu publikuje, jak je znázorněno níže.

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);
}

Nebo můžete vytvořit objekt, který bude představovat ověřovací informace a předat ho jako parametr, jak je znázorněno níže.

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
        };
    }
}

Nikdy byste neměli předávat ID připojení jednoho klienta jiným klientům, protože uživatel se zlými úmysly by ho mohl použít k napodobení požadavku z daného klienta.

Možnosti ověřování pro klienty .NET

Pokud máte klienta .NET, například konzolovou aplikaci, který komunikuje s centrem, které je omezené na ověřené uživatele, můžete ověřovací přihlašovací údaje předat v souboru cookie, v hlavičce připojení nebo v certifikátu. Příklady v této části ukazují, jak tyto různé metody použít k ověřování uživatele. Nejedná se o plně funkční aplikace SignalR. Další informace o klientech .NET se službou SignalR najdete v tématu Průvodce rozhraním API služby Hubs – klient .NET.

Když klient .NET komunikuje s centrem, které používá ověřování pomocí ASP.NET forms, budete muset ručně nastavit ověřovací soubor cookie pro připojení. Soubor cookie přidáte do CookieContainer vlastnosti v objektu HubConnection . Následující příklad ukazuje konzolovou aplikaci, která načte ověřovací soubor cookie z webové stránky a přidá tento soubor cookie do připojení.

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;
        }
    }
}

Konzolová aplikace publikuje přihlašovací údaje do www.contoso.com/RemoteLogin , které by mohly odkazovat na prázdnou stránku, která obsahuje následující soubor kódu na pozadí.

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);
            }
        }
    }
}

Ověřování systému Windows

Při použití ověřování systému Windows můžete předat přihlašovací údaje aktuálního uživatele pomocí vlastnosti DefaultCredentials . Přihlašovací údaje pro připojení nastavíte na hodnotu DefaultCredentials.

class Program
{
    static void Main(string[] args)
    {
        var connection = new HubConnection("http://www.contoso.com/");
        connection.Credentials = CredentialCache.DefaultCredentials;
        connection.Start().Wait();
    }
}

Hlavička připojení

Pokud vaše aplikace soubory cookie nepoužívá, můžete předat informace o uživateli v hlavičce připojení. Můžete například předat token v hlavičce připojení.

class Program
{
    static void Main(string[] args)
    {
        var connection = new HubConnection("http://www.contoso.com/");
        connection.Headers.Add("myauthtoken", /* token data */);
        connection.Start().Wait();
    }
}

Pak byste v centru ověřili token uživatele.

Certifikát

K ověření uživatele můžete předat klientský certifikát. Certifikát přidáte při vytváření připojení. Následující příklad ukazuje pouze postup přidání klientského certifikátu do připojení; nezobrazuje úplnou konzolovou aplikaci. Používá X509Certificate třídy, která poskytuje několik různých způsobů vytvoření certifikátu.

class Program
{
    static void Main(string[] args)
    {
        var connection = new HubConnection("http://www.contoso.com/");
        connection.AddClientCertificate(X509Certificate.CreateFromCertFile("MyCert.cer"));
        connection.Start().Wait();
    }
}