Sdílet prostřednictvím


Ověřování a autorizace center SignalR (SignalR 1.x)

Patrick Fletcher, Tom FitzMacken

Výstraha

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.

Přehled

Toto téma obsahuje následující části:

Autorizovat atribut

SignalR poskytuje atribut Authorize , 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 Authorize použijete buď na rozbočovač, nebo na konkrétní metody v rozbočovači. Když použijete Authorize atribut na třídu centra, použije se zadaný požadavek na autorizaci pro všechny metody v centru. Níže jsou uvedeny různé typy požadavků na autorizaci, které můžete použít. Bez atributu Authorize jsou všechny veřejné metody v centru k dispozici klientovi připojenému k centru.

Pokud jste ve webové aplikaci definovali roli s názvem Správce, můžete určit, že k centru mají přístup pouze 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 posílat jenom někteří uživatelé, ale všichni ostatní můžou zprávu přijmout. Vlastnost RequireOutgoing lze použít pouze pro celý rozbočovač, ne pro jednotlivé metody v rámci rozbočovače. Pokud není požadavek requireOutgoing nastaven na false, ze serveru jsou vyvoláni pouze uživatelé, kteří splňují požadavek na autorizaci.

Vyžadování 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, pokud máte více center a chcete vynutit požadavek na ověření pro všechny z nich. Pomocí této metody nemůžete zadat roli, uživatele ani odchozí autorizaci. Můžete určit, že přístup k metodám centra je omezen pouze na ověřené uživatele. Přesto ale můžete atribut Authorize použít u center nebo metod k určení dalších požadavků. Každý požadavek, který zadáte v atributech, se použije kromě základního požadavku na ověření.

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

public class Global : HttpApplication
{
    void Application_Start(object sender, EventArgs e)
    {
        RouteTable.Routes.MapHubs();
        GlobalHost.HubPipeline.RequireAuthentication();
    }
}

Pokud zavoláte metodu RequireAuthentication() po zpracování požadavku SignalR, SignalR vyvolá InvalidOperationException výjimku. Tato výjimka je vyvolána, protože po vyvolání kanálu nelze do HubPipeline přidat modul. Předchozí příklad ukazuje volání RequireAuthentication metody v Application_Start metodě, která se provádí 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 odvozenou z AuthorizeAttributemetody UserAuthorized a přepsat ji. Tato metoda se volá pro každou žádost, aby určila, jestli má uživatel oprávnění k dokončení požadavku. V přepsané metodě zadáte potřebnou logiku pro scénář autorizace. Následující příklad ukazuje, jak vynutit autorizaci pomocí identity založené na deklaracích nároku.

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

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

Je možné, že 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á publikuje zprávu, 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 představující 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 by ho uživatel se zlými úmysly mohl použít k napodobení žádosti od daného klienta.

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

Pokud máte klienta .NET, jako je konzolová aplikace, která komunikuje s centrem, které je omezené na ověřené uživatele, můžete předávat ověřovací přihlašovací údaje v souboru cookie, hlavičce připojení nebo certifikátu. Příklady v této části ukazují, jak tyto různé metody použít k ověřování uživatele. Nejsou plně funkčními aplikacemi SignalR. Další informace o klientech .NET s knihovnou SignalR naleznete v tématu Průvodce rozhraním API služby Hubs – klient .NET.

Když klient .NET pracuje s centrem, které používá ověřování pomocí ASP.NET formulářů, budete muset v připojení ručně nastavit ověřovací soubor cookie. Do vlastnosti objektu CookieContainer přidáte soubor cookie. 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í. Adresa URL https://www.contoso.com/RemoteLogin v příkladu odkazuje na webovou stránku, kterou byste museli vytvořit. Stránka by načetla publikované uživatelské jméno a heslo a pokusila se uživatele přihlásit pomocí přihlašovacích údajů.

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, na www.contoso.com/RemoteLogin které by mohlo odkazovat na prázdnou stránku, která obsahuje následující soubor kódu.

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 nepoužívá soubory cookie, můžete předat informace o uživateli v hlavičce připojení. Token můžete například předat 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

Můžete předat klientský certifikát k ověření uživatele. Certifikát přidáte při vytváření připojení. Následující příklad ukazuje, pouze jak přidat klientský certifikát do připojení; nezobrazuje úplnou konzolovou aplikaci. Používá třídu X509Certificate , 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();
    }
}