SignalR Hub’ları için Kimlik Doğrulaması ve YetkilendirmeAuthentication and Authorization for SignalR Hubs

, Patrick Fleti, Tom FitzMackenby Patrick Fletcher, Tom FitzMacken

Warning

Bu belge, SignalR 'nin en son sürümü için değildir.This documentation isn't for the latest version of SignalR. ASP.NET Core SignalR'ye göz atın.Take a look at ASP.NET Core SignalR.

Bu konuda, hangi kullanıcıların veya rollerin hub yöntemlerine erişebileceğini nasıl kısıtlayabileceği açıklanmaktadır.This topic describes how to restrict which users or roles can access hub methods.

Bu konuda kullanılan yazılım sürümleriSoftware versions used in this topic

Bu konunun önceki sürümleriPrevious versions of this topic

SignalR 'nin önceki sürümleri hakkında daha fazla bilgi için bkz. SignalR daha eski sürümleri.For information about earlier versions of SignalR, see SignalR Older Versions.

Sorular ve açıklamalarQuestions and comments

Lütfen bu öğreticiyi nasıl beğentireceğiniz ve sayfanın en altındaki açıklamalarda İyileştiğimiz hakkında geri bildirimde bulunun.Please leave feedback on how you liked this tutorial and what we could improve in the comments at the bottom of the page. Öğreticiyle doğrudan ilgili olmayan sorularınız varsa, bunları ASP.NET SignalR forumuna veya StackOverflow.com'e gönderebilirsiniz.If you have questions that are not directly related to the tutorial, you can post them to the ASP.NET SignalR forum or StackOverflow.com.

Genel bakışOverview

Bu konu aşağıdaki bölümleri içermektedir:This topic contains the following sections:

Yetkilendir özniteliğiAuthorize attribute

SignalR, bir hub veya yönteme hangi kullanıcıların veya rollerin erişebileceğini belirtmek için Yetkilendir özniteliği sağlar.SignalR provides the Authorize attribute to specify which users or roles have access to a hub or method. Bu öznitelik Microsoft.AspNet.SignalR ad alanında bulunur.This attribute is located in the Microsoft.AspNet.SignalR namespace. Authorize özniteliğini bir hub 'daki bir hub 'a ya da belirli yöntemlere uygularsınız.You apply the Authorize attribute to either a hub or particular methods in a hub. Authorize özniteliğini bir hub sınıfına uyguladığınızda, belirtilen yetkilendirme gereksinimi, hub 'daki tüm yöntemlere uygulanır.When you apply the Authorize attribute to a hub class, the specified authorization requirement is applied to all of the methods in the hub. Bu konu, uygulayabileceğiniz farklı türlerdeki yetkilendirme gereksinimlerine örnekler sağlar.This topic provides examples of the different types of authorization requirements that you can apply. Authorize özniteliği olmadan bağlı istemci, hub üzerindeki herhangi bir genel yönteme erişebilir.Without the Authorize attribute, a connected client can access any public method on the hub.

Web uygulamanızda "admin" adlı bir rol tanımladıysanız, yalnızca bu roldeki kullanıcıların aşağıdaki kodla bir hub 'a erişebileceğini belirtebilirsiniz.If you have defined a role named "Admin" in your web application, you could specify that only users in that role can access a hub with the following code.

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

Ya da bir hub 'ın tüm kullanıcılar için kullanılabilir bir yöntem içerdiğini ve yalnızca kimliği doğrulanmış kullanıcılar tarafından kullanılabilen ikinci bir yöntemi aşağıda gösterildiği gibi belirtebilirsiniz.Or, you can specify that a hub contains one method that is available to all users, and a second method that is only available to authenticated users, as shown below.

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

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

Aşağıdaki örneklerde farklı yetkilendirme senaryoları ele verilmiştir:The following examples address different authorization scenarios:

  • [Authorize] – yalnızca kimliği doğrulanmış kullanıcılar[Authorize] – only authenticated users
  • [Authorize(Roles = "Admin,Manager")] – yalnızca belirtilen rollerdeki kimliği doğrulanmış kullanıcılar[Authorize(Roles = "Admin,Manager")] – only authenticated users in the specified roles
  • [Authorize(Users = "user1,user2")] – yalnızca belirtilen kullanıcı adlarına sahip kimliği doğrulanmış kullanıcılar[Authorize(Users = "user1,user2")] – only authenticated users with the specified user names
  • [Authorize(RequireOutgoing=false)] – yalnızca kimliği doğrulanmış kullanıcılar hub 'ı çağırabilir, ancak sunucudan istemcilere geri çağrılar bir ileti gönderebildiği ancak diğerlerinin iletiyi alabileceği gibi yetkilendirme ile sınırlı değildir.[Authorize(RequireOutgoing=false)] – only authenticated users can invoke the hub, but calls from the server back to clients are not limited by authorization, such as, when only certain users can send a message but all others can receive the message. Requiregiden özelliği, hub içindeki bireyler yöntemlerine değil, yalnızca tüm Hub 'a uygulanabilir.The RequireOutgoing property can only be applied to the entire hub, not on individuals methods within the hub. Requiregiden değeri false olarak ayarlandığında, yalnızca yetkilendirme gereksinimini karşılayan kullanıcılar sunucudan çağırılır.When RequireOutgoing is not set to false, only users that meet the authorization requirement are called from the server.

Tüm Hub 'lar için kimlik doğrulaması gerektirRequire authentication for all hubs

Uygulama başladığında requiauthentication metodunu çağırarak uygulamanızdaki tüm Hub 'lar ve hub yöntemleri için kimlik doğrulaması yapmanız gerekebilir.You can require authentication for all hubs and hub methods in your application by calling the RequireAuthentication method when the application starts. Birden çok hub olduğunda ve bunların tümü için bir kimlik doğrulama gereksinimini zorlamak istediğinizde bu yöntemi kullanabilirsiniz.You might use this method when you have multiple hubs and want to enforce an authentication requirement for all of them. Bu yöntemde rol, Kullanıcı veya giden yetkilendirme için gereksinimleri belirtemezsiniz.With this method, you cannot specify requirements for role, user, or outgoing authorization. Yalnızca hub yöntemlerine erişimin kimliği doğrulanmış kullanıcılarla kısıtlanmasını belirtebilirsiniz.You can only specify that access to the hub methods is restricted to authenticated users. Bununla birlikte, ek gereksinimler belirtmek için yine de, yetkilendirme özniteliğini hub 'lara veya yöntemlere uygulayabilirsiniz.However, you can still apply the Authorize attribute to hubs or methods to specify additional requirements. Bir öznitelikte belirttiğiniz gereksinim, temel kimlik doğrulaması gereksinimine eklenir.Any requirement you specify in an attribute is added to the basic requirement of authentication.

Aşağıdaki örnek, tüm Hub yöntemlerini kimliği doğrulanmış kullanıcılarla kısıtlayan bir başlangıç dosyası gösterir.The following example shows a Startup file which restricts all hub methods to authenticated users.

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

Bir SignalR isteği işlendikten sonra RequireAuthentication() yöntemini çağırırsanız, SignalR bir InvalidOperationException özel durumu oluşturur.If you call the RequireAuthentication() method after a SignalR request has been processed, SignalR will throw a InvalidOperationException exception. İşlem hattı çağrıldıktan sonra HubPipeline öğesine bir modül ekleyemediği için SignalR bu özel durumu oluşturur.SignalR throws this exception because you cannot add a module to the HubPipeline after the pipeline has been invoked. Önceki örnekte, ilk isteğin işlenmesinden önce bir kez yürütülen Configuration yönteminde RequireAuthentication yönteminin çağrılması gösterilmektedir.The previous example shows calling the RequireAuthentication method in the Configuration method which is executed one time prior to handling the first request.

Özelleştirilmiş yetkilendirmeCustomized authorization

Yetkilendirmenin nasıl belirlendiğini özelleştirmeniz gerekiyorsa, AuthorizeAttribute türeten bir sınıf oluşturabilir ve userauthorization metodunu geçersiz kılabilirsiniz.If you need to customize how authorization is determined, you can create a class that derives from AuthorizeAttribute and override the UserAuthorized method. Her istek için, SignalR kullanıcının isteği tamamlamaya yetkili olup olmadığını belirlemede bu yöntemi çağırır.For each request, SignalR invokes this method to determine whether the user is authorized to complete the request. Geçersiz kılınan yöntemde, yetkilendirme senaryonuz için gerekli mantığı sağlarsınız.In the overridden method, you provide the necessary logic for your authorization scenario. Aşağıdaki örnek, talep tabanlı kimlik aracılığıyla yetkilendirmeyi nasıl zorlayacağı gösterilmektedir.The following example shows how to enforce authorization through claims-based identity.

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

Kimlik doğrulama bilgilerini istemcilere geçirPass authentication information to clients

İstemci üzerinde çalışan koddaki kimlik doğrulama bilgilerini kullanmanız gerekebilir.You may need to use authentication information in the code that runs on the client. İstemci üzerindeki yöntemleri çağırırken gerekli bilgileri geçirirsiniz.You pass the required information when calling the methods on the client. Örneğin, bir sohbet uygulaması yöntemi, aşağıda gösterildiği gibi bir ileti gönderen kişinin kullanıcı adına bir parametre olarak geçirebilir.For example, a chat application method could pass as a parameter the user name of the person posting a message, as shown below.

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

Ya da, aşağıda gösterildiği gibi, kimlik doğrulama bilgilerini temsil eden bir nesne oluşturabilir ve bu nesneyi bir parametre olarak geçirebilirsiniz.Or, you can create an object to represent the authentication information and pass that object as a parameter, as shown below.

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

Kötü niyetli bir Kullanıcı bu istemciden gelen bir isteği taklit etmek için onu kullanabilmesi için, bir istemcinin bağlantı kimliğini asla diğer istemcilere iletmemelisiniz.You should never pass one client's connection id to other clients, as a malicious user could use it to mimic a request from that client.

.NET istemcileri için kimlik doğrulama seçenekleriAuthentication options for .NET clients

Bir konsol uygulaması gibi, kimliği doğrulanmış kullanıcılarla sınırlı bir hub ile etkileşime geçen bir .NET istemciniz varsa, kimlik doğrulama bilgilerini bir tanımlama bilgisine, bağlantı başlığına veya bir sertifikaya geçirebilirsiniz.When you have a .NET client, such as a console app, which interacts with a hub that is limited to authenticated users, you can pass the authentication credentials in a cookie, the connection header, or a certificate. Bu bölümdeki örneklerde, kullanıcının kimliğini doğrulamak için bu farklı yöntemlerin nasıl kullanılacağı gösterilmektedir.The examples in this section show how to use those different methods for authenticating a user. Bunlar tam işlevli SignalR uygulamaları değildir.They are not fully-functional SignalR apps. SignalR ile .NET istemcileri hakkında daha fazla bilgi için bkz. hub API Kılavuzu-.NET istemcisi.For more information about .NET clients with SignalR, see Hubs API Guide - .NET Client.

.NET istemciniz ASP.NET Forms kimlik doğrulaması kullanan bir hub ile etkileşime geçtiğinde, bağlantıda kimlik doğrulama tanımlama bilgisini el ile ayarlamanız gerekir.When your .NET client interacts with a hub that uses ASP.NET Forms Authentication, you will need to manually set the authentication cookie on the connection. Tanımlama bilgisini, Hubconnection nesnesindeki CookieContainer özelliğine eklersiniz.You add the cookie to the CookieContainer property on the HubConnection object. Aşağıdaki örnek, bir Web sayfasından kimlik doğrulama tanımlama bilgisi alan ve bu tanımlama bilgisini bağlantıya ekleyen bir konsol uygulamasını gösterir.The following example shows a console app that retrieves an authentication cookie from a web page and adds that cookie to the connection.

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

Konsol uygulaması, aşağıdaki arka plan kod dosyasını içeren boş bir sayfaya başvuruda bulunmak için kimlik bilgilerini www.contoso.com/RemoteLogin adresine gönderir.The console app posts the credentials to www.contoso.com/RemoteLogin which could refer to an empty page that contains the following code-behind file.

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 kimlik doğrulamasıWindows authentication

Windows kimlik doğrulamasını kullanırken, DefaultCredentials özelliğini kullanarak geçerli kullanıcının kimlik bilgilerini geçirebilirsiniz.When using Windows authentication, you can pass the current user's credentials by using the DefaultCredentials property. DefaultCredentials değeri için bağlantı kimlik bilgilerini ayarlarsınız.You set the credentials for the connection to the value of the DefaultCredentials.

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

Bağlantı üst bilgisiConnection header

Uygulamanız tanımlama bilgilerini kullanmıyor ise, Kullanıcı bilgilerini bağlantı üst bilgisinde geçirebilirsiniz.If your application is not using cookies, you can pass user information in the connection header. Örneğin, bağlantı üst bilgisinde bir belirteç geçirebilirsiniz.For example, you can pass a token in the connection header.

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

Ardından, hub 'da kullanıcının belirtecini doğrularsınız.Then, in the hub, you would verify the user's token.

SertifikaCertificate

Kullanıcıyı doğrulamak için bir istemci sertifikası geçirebilirsiniz.You can pass a client certificate to verify the user. Bağlantıyı oluştururken sertifikayı eklersiniz.You add the certificate when creating the connection. Aşağıdaki örnek, bağlantıya yalnızca bir istemci sertifikasının nasıl ekleneceğini gösterir. tam konsol uygulamasını göstermez.The following example shows only how to add a client certificate to the connection; it does not show the full console app. Sertifikayı oluşturmak için çeşitli farklı yollar sağlayan X509Certificate sınıfını kullanır.It uses the X509Certificate class which provides several different ways to create the certificate.

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