SignalR Hub’ları için Kimlik Doğrulaması ve Yetkilendirme

Patrick Fletcher, Tom FitzMacken tarafından

Uyarı

Bu belgeler SignalR'nin en son sürümüne yönelik değildir. ASP.NET Core SignalR'ye göz atın.

Bu konuda, hangi kullanıcıların veya rollerin hub yöntemlerine erişebileceğini kısıtlama açıklanmaktadır.

Bu konuda kullanılan yazılım sürümleri

Bu konunun önceki sürümleri

SignalR'nin önceki sürümleri hakkında bilgi için bkz. SignalR Eski Sürümleri.

Sorular ve yorumlar

Lütfen bu öğreticiyi nasıl beğendiğiniz ve sayfanın altındaki yorumlarda neleri geliştirebileceğimiz hakkında geri bildirim bırakın. Öğreticiyle doğrudan ilgili olmayan sorularınız varsa bunları ASP.NET SignalR forumunu veya StackOverflow.com gönderebilirsiniz.

Genel Bakış

Bu konu aşağıdaki bölümleri içermektedir:

Authorize özniteliği

SignalR, hangi kullanıcıların veya rollerin bir hub'a veya yönteme erişimi olduğunu belirtmek için Authorize özniteliğini sağlar. Bu öznitelik ad alanında Microsoft.AspNet.SignalR bulunur. özniteliğini Authorize bir hub'a veya hub'daki belirli yöntemlere uygularsınız. özniteliğini bir hub sınıfına Authorize uyguladığınızda, belirtilen yetkilendirme gereksinimi hub'daki tüm yöntemlere uygulanır. Bu konu, uygulayabileceğiniz farklı yetkilendirme gereksinimlerinin örneklerini sağlar. Authorize Özniteliği olmadan, bağlı istemci hub'da herhangi bir genel yönteme erişebilir.

Web uygulamanızda "Yönetici" adlı bir rol tanımladıysanız, aşağıdaki koda sahip bir hub'a yalnızca bu roldeki kullanıcıların erişebileceğini belirtebilirsiniz.

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

İsterseniz, bir hub'ın tüm kullanıcılar için kullanılabilen bir yöntem ve aşağıda gösterildiği gibi yalnızca kimliği doğrulanmış kullanıcıların kullanabileceği ikinci bir yöntem içerdiğini belirtebilirsiniz.

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

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

Aşağıdaki örneklerde farklı yetkilendirme senaryoları ele alınıyor:

  • [Authorize] – yalnızca kimliği doğrulanmış kullanıcılar
  • [Authorize(Roles = "Admin,Manager")] – yalnızca belirtilen rollerdeki kimliği doğrulanmış kullanıcılar
  • [Authorize(Users = "user1,user2")] – yalnızca belirtilen kullanıcı adlarıyla kimliği doğrulanmış kullanıcılar
  • [Authorize(RequireOutgoing=false)] – yalnızca kimliği doğrulanmış kullanıcılar hub'ı çağırabilir, ancak sunucudan istemcilere yapılan çağrılar, yalnızca belirli kullanıcıların ileti gönderebildiği ancak diğer tüm kullanıcıların iletiyi alabileceği durumlar gibi yetkilendirmeyle sınırlı değildir. RequireOutgoing özelliği yalnızca hub'ın tamamına uygulanabilir, hub içindeki bireylere uygulanamayabilir. RequireOutgoing false olarak ayarlanmadığında, sunucudan yalnızca yetkilendirme gereksinimini karşılayan kullanıcılar çağrılır.

Tüm hub'lar için kimlik doğrulaması iste

Uygulama başlatıldığında RequireAuthentication yöntemini çağırarak uygulamanızdaki tüm hub'lar ve hub yöntemleri için kimlik doğrulaması gerektirebilirsiniz. Birden çok hub'larınız olduğunda ve tümü için kimlik doğrulama gereksinimini zorunlu kılmak istediğinizde bu yöntemi kullanabilirsiniz. Bu yöntemle rol, kullanıcı veya giden yetkilendirme gereksinimlerini belirtemezsiniz. Yalnızca hub yöntemlerine erişimin kimliği doğrulanmış kullanıcılarla kısıtlandığını belirtebilirsiniz. Ancak, ek gereksinimleri belirtmek için hub'lara veya yöntemlere Yine de Authorize özniteliğini uygulayabilirsiniz. Bir öznitelikte belirttiğiniz tüm gereksinim, kimlik doğrulamasının temel gereksinimine eklenir.

Aşağıdaki örnekte, tüm hub yöntemlerini kimliği doğrulanmış kullanıcılarla kısıtlayan bir Başlangıç dosyası gösterilmektedir.

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

SignalR isteği işlendikten RequireAuthentication() sonra yöntemini çağırırsanız SignalR bir InvalidOperationException özel durum oluşturur. İşlem hattı çağrıldıktan sonra HubPipeline'e modül ekleyemediğiniz için SignalR bu özel durumu oluşturur. Önceki örnekte, ilk isteği işlemeden önce bir kez yürütülen yönteminde yönteminin Configuration çağrılması RequireAuthentication gösterilmektedir.

Özelleştirilmiş yetkilendirme

Yetkilendirmenin nasıl belirlendiğini özelleştirmeniz gerekiyorsa, UserAuthorized yönteminden AuthorizeAttribute türetilen ve geçersiz kılan bir sınıf oluşturabilirsiniz. Her istek için SignalR, kullanıcının isteği tamamlama yetkisi olup olmadığını belirlemek için bu yöntemi çağırır. Geçersiz kılınan yöntemde yetkilendirme senaryonuz için gerekli mantığı sağlarsınız. Aşağıdaki örnekte, talep tabanlı kimlik aracılığıyla yetkilendirmenin nasıl zorunlu kılındığı gösterilmektedir.

[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çirme

İstemcide çalışan kodda kimlik doğrulama bilgilerini kullanmanız gerekebilir. İstemcide yöntemleri çağırırken gerekli bilgileri geçirirsiniz. Örneğin, bir sohbet uygulaması yöntemi, aşağıda gösterildiği gibi ileti gönderen kişinin kullanıcı adını parametre olarak geçirebilir.

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

Alternatif olarak, aşağıda gösterildiği gibi kimlik doğrulama bilgilerini temsil eden bir nesne oluşturabilir ve bu nesneyi parametre olarak geçirebilirsiniz.

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ü amaçlı bir kullanıcı bu istemciden gelen bir isteği taklit etmek için kullanabileceğinden, bir istemcinin bağlantı kimliğini hiçbir zaman diğer istemcilere geçirmemelisiniz.

.NET istemcileri için kimlik doğrulama seçenekleri

Kimliği doğrulanmış kullanıcılarla sınırlı bir hub ile etkileşim kuran konsol uygulaması gibi bir .NET istemciniz varsa, kimlik doğrulama kimlik bilgilerini bir tanımlama bilgisine, bağlantı üst bilgisine veya sertifikaya geçirebilirsiniz. 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. Bunlar tam işlevsel SignalR uygulamaları değildir. SignalR ile .NET istemcileri hakkında daha fazla bilgi için bkz. Hubs API Kılavuzu - .NET İstemcisi.

.NET istemciniz ASP.NET Forms Kimlik Doğrulaması kullanan bir hub ile etkileşim kurduğunda, bağlantıda kimlik doğrulama tanımlama bilgisini el ile ayarlamanız gerekir. HubConnection nesnesindeki CookieContainer özelliğine tanımlama bilgisini eklersiniz. Aşağıdaki örnekte, bir web sayfasından kimlik doğrulama tanımlama bilgisi alan ve bu tanımlama bilgisini bağlantıya ekleyen bir konsol uygulaması gösterilmektedir.

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ı kimlik bilgilerini www.contoso.com/RemoteLogin gönderir ve bu da aşağıdaki arka planda kod dosyasını içeren boş bir sayfaya başvurabilir.

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 kimlik doğrulamasını kullanırken , DefaultCredentials özelliğini kullanarak geçerli kullanıcının kimlik bilgilerini geçirebilirsiniz. Bağlantının kimlik bilgilerini DefaultCredentials değerine ayarlarsınız.

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 bilgisi

Uygulamanız tanımlama bilgileri kullanmıyorsa, bağlantı üst bilgisinde kullanıcı bilgilerini geçirebilirsiniz. Örneğin, bağlantı üst bilgisinde bir belirteç geçirebilirsiniz.

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ğrulayabilirsiniz.

Sertifika

Kullanıcıyı doğrulamak için bir istemci sertifikası geçirebilirsiniz. Bağlantıyı oluştururken sertifikayı eklersiniz. Aşağıdaki örnekte yalnızca bağlantıya bir istemci sertifikasının nasıl ekleneceği gösterilmektedir; tam konsol uygulamasını göstermez. Sertifikayı oluşturmak için birkaç farklı yol sağlayan X509Certificate sınıfını kullanır.

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