Share via


SignalR Hub’ları için Kimlik Doğrulaması ve Yetkilendirme (SignalR 1.x)

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.

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. Uygulayabileceğiniz farklı yetkilendirme gereksinimleri aşağıda gösterilmiştir. Authorize özniteliği olmadan, hub'daki tüm genel yöntemler hub'a bağlı bir istemci tarafından kullanılabilir.

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 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. Özniteliklerde belirttiğiniz tüm gereksinim, kimlik doğrulamasının temel gereksinimine ek olarak uygulanır.

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

public class Global : HttpApplication
{
    void Application_Start(object sender, EventArgs e)
    {
        RouteTable.Routes.MapHubs();
        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 bu özel durum oluşturulur. Önceki örnekte, ilk isteği işlemeden önce bir kez yürütülen yönteminde yönteminin Application_Start ç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. Bu yöntem, kullanıcının isteği tamamlama yetkisi olup olmadığını belirlemek üzere her istek için çağrılı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 = (ClaimsPrincipal)user;

        if (principal != null)
        {
            Claim authenticated = principal.FindFirst(ClaimTypes.Authentication);
            return authenticated.Value == "true" ? true : 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. Örnekteki URL https://www.contoso.com/RemoteLogin , oluşturmanız gereken bir web sayfasına işaret eder. Sayfa, gönderilen kullanıcı adını ve parolayı alır ve kullanıcıda kimlik bilgileriyle oturum açmayı dener.

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