しばやん雑記

Azure とメイドさんが大好きなフリーランスのプログラマーのブログ

ASP.NET SignalR の認証について

ASP.NET SignalR 1.0 では MVC や Web API のように属性を使った認証に対応しました。以前から要求が多かったのに対応が遅くなったのには、SignalR に特有の事情がありました。

そして今回、実際に実装された Authorize 属性を見ると Role や User といった MVC 互換のプロパティの他に Mode という AuthorizeMode 型のプロパティが追加されています。AuthorizeMode 型には Incoming/Outgoing/Both の 3 つの値が定義されていて、それぞれ挙動が異なりますので調査しました。

今回サンプルとして使用する、基本となる Hub の実装です。

[Authorize]
[HubName("auth")]
public class AuthHub : Hub
{
    public string Incoming()
    {
        return "OK";
    }

    public void Outgoing()
    {
        Clients.All.Receive("OK");
    }
}

Incoming メソッドは単純に値を返すだけ、Outgoing メソッドは全てのクライアントへプッシュを行います。それでは、AuthorizeMode の値を変更して確認していきます。

そして実際にハブのメソッドを呼び出す JavaScript は以下のようになります。

$(function() {
    var connection = $.hubConnection();
    var auth = connection.createHubProxy("auth");

    auth.on("Receive", function (result) {
        alert(result);
    });

    connection.start(function() {
        //auth.invoke("Incoming");
        //auth.invoke("Outgoing");
    });
});

実際のメソッド呼び出しはコメントを削除して Incoming と Outgoing の時でそれぞれ切り替えて試すようにします。

AuthorizeMode.Incoming

クライアントからサーバへの通信に対して認証を要求する。

[Authorize(Mode = AuthorizeMode.Incoming)]
[HubName("auth")]
public class AuthHub : Hub
{
    public string Incoming()
    {
        return "OK";
    }

    public void Outgoing()
    {
        Clients.All.Receive("OK");
    }
}

Incoming はクライアントからのリクエストに対して認証を要求します。ですので、実際の挙動は MVC や Web API の Authorize 属性に非常に似ています。

つまりログインしていない状態では invoke メソッドの呼び出しはブロックされますが、on メソッドで定義した関数は呼び出されます。

AuthorizeMode.Outgoing

サーバからクライアントへの通信に対して認証を要求する。

[Authorize(Mode = AuthorizeMode.Outgoing)]
[HubName("auth")]
public class AuthHub : Hub
{
    public string Incoming()
    {
        return "OK";
    }

    public void Outgoing()
    {
        Clients.All.Receive("OK");
    }
}

Outgoing の挙動は Incoming と比べて、ちょっと理解しにくい感じです。サーバからクライアントへの通信に対して認証を要求するので、別のクライアントによるブロードキャスト要求もブロックされることになります。

つまり on メソッドで定義した関数はブロックされますが、invoke メソッドでの呼び出しは成功します。

AuthorizeMode.Both

[Authorize(Mode = AuthorizeMode.Both)]
[HubName("auth")]
public class AuthHub : Hub
{
    public string Incoming()
    {
        return "OK";
    }

    public void Outgoing()
    {
        Clients.All.Receive("OK");
    }
}

Both はその名の通り Incoming と Outgoing を組み合わせたものなので、MVC や Web API の Authorize とほぼ同じです。Authorize 属性のデフォルトは Both なので、AuthorizeMode を指定しない使い方が一般的かと思います。