SignalR ハブの認証と承認 (SignalR 1.x)Authentication and Authorization for SignalR Hubs (SignalR 1.x)

によってPatrick FletcherTom FitzMackenby Patrick Fletcher, Tom FitzMacken

Note

この記事では、ASP.NET SignalR を指します。This article refers to ASP.NET SignalR. SignalR を使用して、Java、Node.js、またはサーバーレス シナリオでは、リアルタイムのシナリオを有効にする方法と思う場合を見てASP.NET Core SignalRします。If you're thinking about using SignalR to enable real-time scenarios with Java, Node.js, or in a serverless scenario, take a look at ASP.NET Core SignalR. 既に ASP.NET SignalR を使用した場合を見て、のバージョンの違いバージョンの違いと ASP.NET Core SignalR での機能強化を理解するページ。If you've already used ASP.NET SignalR, take a look at the version differences page to understand the differences in the versions and the improvements in ASP.NET Core SignalR. 最後に、Microsoft Azure でリアルタイム アプリを実行することがわかっている場合を見て、 Azure SignalR サービスなど、アプリを必要とすると、クラウド ベースのスケール アウトを提供します。Finally, if you know you'll be running your real-time apps in Microsoft Azure, take a look at the Azure SignalR Service, as it provides cloud-based scale-out once your apps need it.

このトピックでは、どのユーザーまたはロールがハブ メソッドにアクセスできる制限する方法について説明します。This topic describes how to restrict which users or roles can access hub methods.

概要Overview

このトピックは、次のセクションで構成されています。This topic contains the following sections:

属性を承認します。Authorize attribute

SignalR の提供、 Authorizeハブまたはメソッドへのアクセスを持つユーザーまたはロールを指定する属性。SignalR provides the Authorize attribute to specify which users or roles have access to a hub or method. この属性にある、Microsoft.AspNet.SignalR名前空間。This attribute is located in the Microsoft.AspNet.SignalR namespace. 適用する、Authorize属性をハブまたはハブ内の特定のメソッドのいずれか。You apply the Authorize attribute to either a hub or particular methods in a hub. 適用すると、 Authorize hub クラスでは、指定された承認要件を属性のすべてのハブ メソッドに適用されます。When you apply the Authorize attribute to a hub class, the specified authorization requirement is applied to all of the methods in the hub. 適用できる承認要件のさまざまな種類は、以下に示します。The different types of authorization requirements that you can apply are shown below. なし、Authorize属性、ハブのすべてのパブリック メソッドは、ハブに接続されているクライアントで使用します。Without the Authorize attribute, all public methods on the hub are available to a client that is connected to the hub.

Web アプリケーションで"Admin"をという名前のロールを定義している場合は、次のコードでのハブをそのロール内のユーザーのみがアクセスできることを指定できます。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 
{ 
}

または、すべてのユーザーに提供される 1 つのメソッドと 2 番目のメソッドのみが利用できる認証されたユーザーは、次に示すようにハブが含まれているを指定することができます。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){ . . . } 
}

次の例は、さまざまな承認シナリオに対処します。The following examples address different authorization scenarios:

  • [Authorize] -認証されたユーザーのみ– only authenticated users
  • [Authorize(Roles = "Admin,Manager")] – 指定したロールのユーザーを認証されたのみ– only authenticated users in the specified roles
  • [Authorize(Users = "user1,user2")] – 指定されたユーザー名を持つユーザーを認証されたのみ– only authenticated users with the specified user names
  • [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. RequireOutgoing プロパティは、ハブ内の個人メソッドではなく、全体のハブにのみ適用できます。The RequireOutgoing property can only be applied to the entire hub, not on individuals methods within the hub. RequireOutgoing が false に設定されていない場合は、サーバーから承認要件を満たすユーザーのみが呼び出されます。When RequireOutgoing is not set to false, only users that meet the authorization requirement are called from the server.

すべてのハブの認証が必要です。Require authentication for all hubs

アプリケーションで呼び出すことによってすべてのハブおよびハブ メソッドの認証を要求できます、 RequireAuthenticationメソッド、アプリケーションの起動時にします。You can require authentication for all hubs and hub methods in your application by calling the RequireAuthentication method when the application starts. 複数のハブおよびすべての認証の要件を適用するした場合、このメソッドを使用する場合があります。You might use this method when you have multiple hubs and want to enforce an authentication requirement for all of them. この方法では、ロール、ユーザー、または送信の承認を指定できません。With this method, you cannot specify role, user, or outgoing authorization. ハブ メソッドへのアクセスが認証されたユーザーに制限のみ指定することができます。You can only specify that access to the hub methods is restricted to authenticated users. ただし、ハブまたはその他の要件を指定するメソッドに、Authorize 属性を適用できます。However, you can still apply the Authorize attribute to hubs or methods to specify additional requirements. 属性で指定する必要は、認証の基本的な要件に加えて適用されます。Any requirement you specify in attributes is applied in addition to the basic requirement of authentication.

次の例では、すべてのハブ メソッドを認証されたユーザーに制限する Global.asax ファイルを示します。The following example shows a Global.asax file which restricts all hub methods to authenticated users.

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

呼び出す場合、RequireAuthentication()メソッド SignalR 要求の処理が完了したら、SignalR がスローされます、InvalidOperationException例外。If you call the RequireAuthentication() method after a SignalR request has been processed, SignalR will throw a InvalidOperationException exception. パイプラインが呼び出された後、モジュールを HubPipeline に追加することはできませんので、この例外がスローされます。This exception is thrown because you cannot add a module to the HubPipeline after the pipeline has been invoked. 前の例では、呼び出しを示しています、RequireAuthenticationメソッドで、Application_Startメソッドの最初の要求を処理する前に 1 回実行されます。The previous example shows calling the RequireAuthentication method in the Application_Start method which is executed one time prior to handling the first request.

カスタマイズされた承認Customized authorization

派生したクラスを作成するには承認を決定する方法をカスタマイズする必要がある場合AuthorizeAttributeをオーバーライドし、 UserAuthorizedメソッド。If you need to customize how authorization is determined, you can create a class that derives from AuthorizeAttribute and override the UserAuthorized method. このメソッドは、ユーザーに承認要求を完了するかどうかを判断するには、各要求に対して呼び出されます。This method is called for each request to determine whether the user is authorized to complete the request. オーバーライドされたメソッドで、承認のシナリオに必要なロジックを提供します。In the overridden method, you provide the necessary logic for your authorization scenario. 次の例では、クレーム ベース id 経由で認証を実行する方法を示します。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 = (ClaimsPrincipal)user;

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

クライアントに認証情報を渡すPass authentication information to clients

クライアントで実行されるコードで認証情報を使用する必要があります。You may need to use authentication information in the code that runs on the client. クライアントでメソッドの呼び出し時に、必要な情報を渡します。You pass the required information when calling the methods on the client. たとえば、チャット アプリケーションの方法でしたをパラメーターとして渡す、メッセージを投稿する人のユーザー名次に示すよう。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);
}

または、次に示すように認証情報を表し、そのオブジェクトをパラメーターとして渡すオブジェクトを作成することができます。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
        };
    }
}

悪意のあるユーザーがそのクライアントからの要求を模倣するために使用できますよう他のクライアントに 1 つのクライアント接続 id を渡してください。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 クライアントの認証オプションAuthentication options for .NET clients

認証されたユーザーを制限するハブとの対話、により、コンソール アプリなどの .NET クライアントがある場合は、cookie、connection ヘッダー。 または、証明書で認証資格情報を渡すことができます。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. このセクションの例では、ユーザーを認証するため、これらのさまざまなメソッドを使用する方法を示します。The examples in this section show how to use those different methods for authenticating a user. 完全に機能する SignalR アプリケーションではありません。They are not fully-functional SignalR apps. SignalR を使って .NET クライアントの詳細については、次を参照してください。ハブ API ガイド - .NET クライアントします。For more information about .NET clients with SignalR, see Hubs API Guide - .NET Client.

ASP.NET フォーム認証を使用するハブを操作すると、.NET クライアント、接続の認証クッキーを手動で設定する必要があります。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. Cookie を追加する、CookieContainerプロパティをHubConnectionオブジェクト。You add the cookie to the CookieContainer property on the HubConnection object. 次の例では、web ページから、認証 cookie を取得し、接続をそのクッキーを追加します。 コンソール アプリを示します。The following example shows a console app that retrieves an authentication cookie from a web page and adds that cookie to the connection. URLhttps://www.contoso.com/RemoteLoginで例を作成する必要のある web ページ。The URL https://www.contoso.com/RemoteLogin in the example points to a web page that you would need to create. ページは、ポストされたユーザー名とパスワードを取得し、資格情報でユーザーにログインしようとしています。The page would retrieve the posted user name and password, and attempt to log in the user with the credentials.

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

コンソール アプリはでした次のコード ビハインド ファイルを含む空のページを参照している www.contoso.com/RemoteLogin に資格情報を送信します。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 認証Windows authentication

Windows 認証を使用する場合を使用して現在のユーザーの資格情報を渡すことができます、される DefaultCredentialsプロパティ。When using Windows authentication, you can pass the current user's credentials by using the DefaultCredentials property. される DefaultCredentials の値には、接続の資格情報を設定します。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();
    }
}

接続ヘッダーConnection header

アプリケーションが cookie を使用していない場合は、ユーザー情報を接続ヘッダーで渡すことができます。If your application is not using cookies, you can pass user information in the connection header. たとえば、接続ヘッダーでトークンを渡すことができます。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();
    }
}

次に、ハブでは、ユーザーのトークンを確認します。Then, in the hub, you would verify the user's token.

証明書Certificate

ユーザーを確認するクライアント証明書を渡すことができます。You can pass a client certificate to verify the user. 接続を作成するときに、証明書を追加します。You add the certificate when creating the connection. 次の例では、接続にクライアント証明書を追加する方法のみを示しています。完全なコンソール アプリは表示されません。The following example shows only how to add a client certificate to the connection; it does not show the full console app. 使用して、 X509Certificateクラス、証明書を作成するいくつかの方法を提供します。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();
    }
}