Azure Functions における SignalR Service の入力バインド

クライアントが Azure SignalR Service に接続するには、そのクライアントに、サービス エンドポイント URL と有効なアクセス トークンが必要です。 サービスへの接続に使用される SignalR Service エンドポイント URL と有効なトークンは、SignalRConnectionInfo 入力バインドによって生成されます。 トークンは時間制限があり、接続に対して特定のユーザーを認証するために使用できます。 そのため、トークンをキャッシュしたり、クライアント間で共有したりしないでください。 通常、クライアントが接続情報を取得するには、SignalRConnectionInfo と HTTP トリガーを使用します。

このバインドを使用して SignalR クライアント SDK と互換性のある "negotiate" 関数を作成する方法の詳細については、「Azure SignalR Service を使用した Azure Functions の開発と構成」を参照してください。

明示的に宣言されていない場合は、 AzureSignalRConnectionStringの既定の接続設定値を使用している例を想定します。 セットアップと構成の詳細については、概要に関するページをご覧ください。

C# 関数は、次のいずれかの C# モードを使用して作成できます。

  • 分離されたワーカー モデル: ランタイムから分離されたワーカー プロセスで実行されるコンパイル済みの C# 関数。 .NET および .NET Framework の長期サポート (LTS) および LTS 以外のバージョンで実行されている C# 関数をサポートするには、分離ワーカー プロセスが必要です。
  • インプロセス モデル: Azure Functions ランタイムと同じプロセスで実行されるコンパイル済み C# 関数。
  • C# スクリプト: Azure portal で C# 関数を作成するときに主に使用されます。

次の例は、入力バインドを使用して SignalR 接続情報を取得し、HTTP 経由でそれを返す C# 関数を示しています。

[Function(nameof(Negotiate))]
public static string Negotiate([HttpTrigger(AuthorizationLevel.Anonymous)] HttpRequestData req,
    [SignalRConnectionInfoInput(HubName = "serverless")] string connectionInfo)
{
    // The serialization of the connection info object is done by the framework. It should be camel case. The SignalR client respects the camel case response only.
    return connectionInfo;
}

次の例は、function.json ファイル内の SignalR 接続情報入力バインディングと、そのバインディングを使用して接続情報を返す関数を示しています。

function.json ファイル内の例のバインディング データを次に示します。

{
    "type": "signalRConnectionInfo",
    "name": "connectionInfo",
    "hubName": "hubName1",
    "connectionStringSetting": "<name of setting containing SignalR Service connection string>",
    "direction": "in"
}

JavaScript コードを次に示します。

const { app, input } = require('@azure/functions');

const inputSignalR = input.generic({
    type: 'signalRConnectionInfo',
    name: 'connectionInfo',
    hubName: 'hubName1',
    connectionStringSetting: 'AzureSignalRConnectionString',
});

app.post('negotiate', {
    authLevel: 'function',
    handler: (request, context) => {
        return { body: JSON.stringify(context.extraInputs.get(inputSignalR)) }
    },
    route: 'negotiate',
    extraInputs: [inputSignalR],
});

PowerShell の完全な例は保留中です。

次の例は、function.json ファイルの SignalR 接続情報入力バインドと、そのバインドを使用して接続情報を返す Python 関数を示しています。

Python コードを次に示します。

def main(req: func.HttpRequest, connectionInfoJson: str) -> func.HttpResponse:
    return func.HttpResponse(
        connectionInfoJson,
        status_code=200,
        headers={
            'Content-type': 'application/json'
        }
    )

次の例は、入力バインドを使用して SignalR 接続情報を取得し、HTTP 経由でそれを返す Java 関数を示しています。

@FunctionName("negotiate")
public SignalRConnectionInfo negotiate(
        @HttpTrigger(
            name = "req",
            methods = { HttpMethod.POST },
            authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> req,
        @SignalRConnectionInfoInput(
            name = "connectionInfo",
            HubName = "hubName1") SignalRConnectionInfo connectionInfo) {
    return connectionInfo;
}

属性

インプロセス分離ワーカー プロセスの C# ライブラリの両方で、属性を使用して関数を定義します。 C# スクリプトでは、代わりに function.json 構成ファイルを使います。

次の表では、SignalRConnectionInfoInput 属性のプロパティについて説明します。

属性のプロパティ 説明
HubName 必須。 ハブ名。
ConnectionStringSetting SignalR Service 接続文字列を含むアプリ設定または設定コレクションの名前。既定ではAzureSignalRConnectionString
UserId 省略可能。 SignalR 接続のユーザー識別子。 バインド式を使用して、値を HTTP 要求ヘッダーまたはクエリにバインドできます。
IdToken 省略可能。 ユーザー要求に要求が追加される JWT。 ClaimTypeList と共に使用する必要があります。 バインド式を使用して、値を HTTP 要求ヘッダーまたはクエリにバインドできます。
ClaimTypeList 省略可能。 IdToken の要求をフィルター処理する要求の種類の一覧。

注釈

次の表では、SignalRConnectionInfoInput 注釈でサポートされている設定について説明します。

設定 説明
名前 接続情報オブジェクトの関数コードで使用される変数名。
hubName 必須。 ハブ名。
connectionStringSetting SignalR Service 接続文字列を含むアプリ設定または設定コレクションの名前。既定ではAzureSignalRConnectionString
userId 省略可能。 SignalR 接続のユーザー識別子。 バインド式を使用して、値を HTTP 要求ヘッダーまたはクエリにバインドできます。
idToken 省略可能。 ユーザー要求に要求が追加される JWT。 claimTypeList と共に使用する必要があります。 バインド式を使用して、値を HTTP 要求ヘッダーまたはクエリにバインドできます。
claimTypeList 省略可能。 idToken の要求をフィルター処理する要求の種類の一覧。

注釈

次の表では、SignalRConnectionInfoInput 注釈でサポートされている設定について説明します。

設定 説明
名前 接続情報オブジェクトの関数コードで使用される変数名。
hubName 必須。 ハブ名。
connectionStringSetting SignalR Service 接続文字列を含むアプリ設定または設定コレクションの名前。既定ではAzureSignalRConnectionString
userId 省略可能。 SignalR 接続のユーザー識別子。 バインド式を使用して、値を HTTP 要求ヘッダーまたはクエリにバインドできます。
idToken 省略可能。 ユーザー要求に要求が追加される JWT。 claimTypeList と共に使用する必要があります。 バインド式を使用して、値を HTTP 要求ヘッダーまたはクエリにバインドできます。
claimTypeList 省略可能。 idToken の要求をフィルター処理する要求の種類の一覧。

構成

次の表は、function.json ファイルで設定したバインド構成のプロパティを説明しています。

function.json のプロパティ 説明
タイプ signalRConnectionInfo に設定する必要があります。
方向 in に設定する必要があります。
hubName 必須。 ハブ名。
connectionStringSetting SignalR Service 接続文字列を含むアプリ設定または設定コレクションの名前。既定ではAzureSignalRConnectionString
userId 省略可能。 SignalR 接続のユーザー識別子。 バインド式を使用して、値を HTTP 要求ヘッダーまたはクエリにバインドできます。
idToken 省略可能。 ユーザー要求に要求が追加される JWT。 claimTypeList と共に使用する必要があります。 バインド式を使用して、値を HTTP 要求ヘッダーまたはクエリにバインドできます。
claimTypeList 省略可能。 idToken の要求をフィルター処理する要求の種類の一覧。

警告

わかりやすくするために、このサンプルでは認証と認可の部分を省略しています。 その結果、このエンドポイントは制限なしでパブリックにアクセスできます。 ネゴシエーション エンドポイントのセキュリティを確保するには、特定の要件に基づいて適切な認証と認可メカニズムを実装する必要があります。 HTTP エンドポイントの保護に関するガイダンスについては、次の記事を参照してください。

使用方法

接続

connectionStringSettingプロパティはアプリケーション設定でキーに設定されており、Functionsランタイムが拡張で使うAzure SignalR Serviceインスタンスに接続するために使う値を返します。 この接続プロパティ設定の値は接続の種類によって異なります。

  • マネージド・アイデンティティ接続: connectionStringSetting プロパティは、複数の設定が共有する <CONNECTION_NAME_PREFIX> であり、これらが共にサービスエンドポイントへのアイデンティティベースの接続を定義します。 詳細については、「 同一性接続の定義」を参照してください。
  • Key Vault参照:connectionStringSettingプロパティ設定は、接続文字列が中央管理されている場所への参照Azure Key Vaultを返します。 詳細については、「Key Vault connectionsの定義」をご覧ください。
  • App Configuration reference:connectionStringSettingプロパティ設定は接続文字列またはKey Vault参照を返すAzure App Configuration参照を返します。 詳細については、接続記事のAzure App Configurationをご覧ください。
  • Connection string:connectionStringSettingプロパティ設定は実際のSignalRサービス接続文字列を返します。 接続文字列には共有の秘密鍵が含まれているため、可能であれば管理型アイデンティティ接続の使用を検討すべきです。 詳細については、「 接続の定義」を参照してください。

バインディング接続について詳しく知りたい方は、Azure Functionsの「Manage connection in Connection」をご覧ください。 接続文字列を取得するには、「How to get 接続文字列s」の手順に従ってください。

Functionsホストは、SignalRサービスに接続する際に AzureSignalRConnectionString という名前のキーまたはキープレフィックスを探します。 そうでなければ、 connectionStringSetting で設定されたキー値を用いて必要な接続情報を取得します。

認証済みトークン

認証済みクライアントによって関数がトリガーされている場合は、ユーザー ID 要求を生成済みトークンに追加できます。 App Service 認証を使用すると、認証を関数アプリに簡単に追加することができます。

App Service 認証では、それぞれ、認証されたユーザーのクライアント プリンシパルの ID と名前が含まれている x-ms-client-principal-idx-ms-client-principal-name という名前の HTTP ヘッダーが設定されます。

バインドの UserId プロパティをいずれかのヘッダーの値に設定するには、バインド式として {headers.x-ms-client-principal-id} または {headers.x-ms-client-principal-name} を使用します。

[Function("Negotiate")]
public static string Negotiate([HttpTrigger(AuthorizationLevel.Anonymous)] HttpRequestData req,
    [SignalRConnectionInfoInput(HubName = "hubName1", UserId = "{headers.x-ms-client-principal-id}")] string connectionInfo)
{
    // The serialization of the connection info object is done by the framework. It should be camel case. The SignalR client respects the camel case response only.
    return connectionInfo;
}
@FunctionName("negotiate")
public SignalRConnectionInfo negotiate(
        @HttpTrigger(
            name = "req",
            methods = { HttpMethod.POST, HttpMethod.GET },
            authLevel = AuthorizationLevel.ANONYMOUS)
            HttpRequestMessage<Optional<String>> req,
        @SignalRConnectionInfoInput(name = "connectionInfo", hubName = "hubName1", userId = "{headers.x-ms-signalr-userid}") SignalRConnectionInfo connectionInfo) {
    return connectionInfo;
}

function.json ファイルのバインド データを次に示します。

{
    "type": "signalRConnectionInfo",
    "name": "connectionInfo",
    "hubName": "hubName1",
    "userId": "{headers.x-ms-client-principal-id}",
    "connectionStringSetting": "<name of setting containing SignalR Service connection string>",
    "direction": "in"
}

JavaScript コードを次に示します。

const { app, input } = require('@azure/functions');

const inputSignalR = input.generic({
    type: 'signalRConnectionInfo',
    name: 'connectionInfo',
    hubName: 'hubName1',
    connectionStringSetting: 'AzureSignalRConnectionString',
    userId: '{headers.x-ms-client-principal-id}',
});

app.post('negotiate', {
    authLevel: 'function',
    handler: (request, context) => {
        return { body: JSON.stringify(context.extraInputs.get(inputSignalR)) }
    },
    route: 'negotiate',
    extraInputs: [inputSignalR],
});

PowerShell の完全な例は保留中です。

Python コードを次に示します。

def main(req: func.HttpRequest, connectionInfo: str) -> func.HttpResponse:
    # connectionInfo contains an access key token with a name identifier
    # claim set to the authenticated user
    return func.HttpResponse(
        connectionInfo,
        status_code=200,
        headers={
            'Content-type': 'application/json'
        }
    )
@FunctionName("negotiate")
public SignalRConnectionInfo negotiate(
        @HttpTrigger(
            name = "req",
            methods = { HttpMethod.POST },
            authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> req,
        @SignalRConnectionInfoInput(
            name = "connectionInfo",
            HubName = "hubName1",
            userId = "{headers.x-ms-client-principal-id}") SignalRConnectionInfo connectionInfo) {
    return connectionInfo;
}

HTTP トリガーのバインド式

これは、SignalR 入力バインディングの一部の属性の値が HTTP 要求で取得される一般的なシナリオです。 そのため、バインド式を介して HTTP 要求の値を SignalR 入力バインド属性にバインドする方法を示します。

HTTP メタデータの種類 バインド式の形式 説明
HTTP 要求クエリ {query.QUERY_PARAMETER_NAME} 対応するクエリ パラメーターの値を属性にバインドする {query.userName}
HTTP 要求ヘッダー {headers.HEADER_NAME} ヘッダーの値を属性にバインドする {headers.token}

次のステップ