Azure Functions 的 SignalR 服务输入绑定
客户端在连接到 Azure SignalR 服务之前,必须检索服务终结点 URL 和有效的访问令牌。 SignalRConnectionInfo 输入绑定生成 SignalR 服务终结点 URL 和有效的令牌,这两者可以用来连接到服务。 此令牌有时间限制,并且可用来对需要连接的特定用户进行身份验证。 因此,请勿缓存令牌或在客户端之间共享令牌。 通常,将 SignalRConnectionInfo 与 HTTP 触发器配合使用,以便客户端检索连接信息。
有关如何使用此绑定来创建一个与 SignalR 客户端 SDK 兼容的“协商”函数的详细信息,请参阅使用 Azure SignalR 服务进行 Azure Functions 开发和配置一文。 若要了解设置和配置详细信息,请参阅概述。
示例
可使用以下 C# 模式之一来创建 C# 函数:
- 进程内类库:编译的 C# 函数,该函数在与 Functions 运行时相同的进程中运行。
- 独立工作进程类库:编译的 C# 函数,该函数在独立于运行时的工作进程中运行。 需要独立工作进程才能支持在 LTS 和非 LTS 版 .NET 和 .NET Framework 上运行的 C# 函数。
- C# 脚本:主要在 Azure 门户中创建 C# 函数时使用。
重要
对进程内模型的支持将于 2026 年 11 月 10 日结束。 为获得完全支持,强烈建议将应用迁移到独立工作模型。
以下示例演示了一个 C# 函数,该函数使用输入绑定获取 SignalR 连接信息,并通过 HTTP 将其返回。
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
using System.Text.Json;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
namespace Extensions.SignalR
{
public static class SignalRNegotiationFunctions
{
// <snippet_negotiate>
[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;
}
// </snippet_negotiate>
// When you have multiple SignalR service instances and you want to customize the rule that route a client
// <snippet_negotiate_multiple_endpoint>
public static readonly JsonSerializerOptions SerializerOptions = new()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};
[Function(nameof(NegotiateWithMultipleEndpoints))]
public static string NegotiateWithMultipleEndpoints(
[HttpTrigger(AuthorizationLevel.Anonymous)] HttpRequestData req,
[SignalRNegotiationInput("chatHub", "SignalRConnection")] SignalRNegotiationContext negotiationContext)
{
// Customize your rule here
var connectionInfo = negotiationContext.Endpoints[0].ConnectionInfo;
// The SignalR client respects the camel case response only.
return JsonSerializer.Serialize(connectionInfo, SerializerOptions);
}
// </snippet_negotiate_multiple_endpoint>
}
}
以下示例演示了 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'
}
)
以下示例演示了一个 Java 函数,该函数使用输入绑定获取 SignalR 连接信息,并通过 HTTP 将其返回。
@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;
}
使用情况
已进行身份验证的令牌
当此函数由经过身份验证的客户端触发时,可向生成的令牌添加用户 ID 声明。 可以轻松地使用应用服务身份验证向函数应用添加身份验证。
应用服务身份验证会设置名为 x-ms-client-principal-id
和 x-ms-client-principal-name
(分别包含经身份验证的用户的客户端主体 ID 和名称)的 HTTP 标头。
可以使用绑定表达式{headers.x-ms-client-principal-id}
或 {headers.x-ms-client-principal-name}
将绑定的 UserId
属性设置为任一标头中的值。
[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;
}
特性
进程内和独立工作进程 C# 库都使用特性来定义函数。 C# 脚本改为使用 function.json 配置文件。
下表说明了 SignalRConnectionInfoInput
特性的属性:
Attribute 属性 | 说明 |
---|---|
HubName | 必需。 中心名称。 |
ConnectionStringSetting | 包含 SignalR 服务连接字符串(默认为 AzureSignalRConnectionString )的应用设置的名称。 |
UserId | 可选。 SignalR 连接的用户标识符。 可以使用绑定表达式将值绑定到 HTTP 请求头或查询。 |
IdToken | 可选。 一个 JWT 令牌,其声明将添加到用户声明中。 应与 ClaimTypeList 一起使用。 可以使用绑定表达式将值绑定到 HTTP 请求头或查询。 |
ClaimTypeList | 可选。 声明类型的列表,用于筛选 IdToken 中的声明。 |
批注
下表说明了 SignalRConnectionInfoInput
批注的受支持的设置。
设置 | 说明 |
---|---|
name | 变量名称,在连接信息对象的函数代码中使用。 |
hubName | 必需。 中心名称。 |
connectionStringSetting | 包含 SignalR 服务连接字符串(默认为 AzureSignalRConnectionString )的应用设置的名称。 |
userId | 可选。 SignalR 连接的用户标识符。 可以使用绑定表达式将值绑定到 HTTP 请求头或查询。 |
idToken | 可选。 一个 JWT 令牌,其声明将添加到用户声明中。 应与 claimTypeList 一起使用。 可以使用绑定表达式将值绑定到 HTTP 请求头或查询。 |
claimTypeList | 可选。 声明类型的列表,用于筛选 idToken 中的声明。 |
批注
下表说明了 SignalRConnectionInfoInput
批注的受支持的设置。
设置 | 说明 |
---|---|
name | 变量名称,在连接信息对象的函数代码中使用。 |
hubName | 必需。 中心名称。 |
connectionStringSetting | 包含 SignalR 服务连接字符串(默认为 AzureSignalRConnectionString )的应用设置的名称。 |
userId | 可选。 SignalR 连接的用户标识符。 可以使用绑定表达式将值绑定到 HTTP 请求头或查询。 |
idToken | 可选。 一个 JWT 令牌,其声明将添加到用户声明中。 应与 claimTypeList 一起使用。 可以使用绑定表达式将值绑定到 HTTP 请求头或查询。 |
claimTypeList | 可选。 声明类型的列表,用于筛选 idToken 中的声明。 |
配置
下表解释了在 function.json 文件中设置的绑定配置属性。
“function.json”属性 | 说明 |
---|---|
type | 必须设置为 signalRConnectionInfo 。 |
direction | 必须设置为 in 。 |
hubName | 必需。 中心名称。 |
connectionStringSetting | 包含 SignalR 服务连接字符串(默认为 AzureSignalRConnectionString )的应用设置的名称。 |
userId | 可选。 SignalR 连接的用户标识符。 可以使用绑定表达式将值绑定到 HTTP 请求头或查询。 |
idToken | 可选。 一个 JWT 令牌,其声明将添加到用户声明中。 应与 claimTypeList 一起使用。 可以使用绑定表达式将值绑定到 HTTP 请求头或查询。 |
claimTypeList | 可选。 声明类型的列表,用于筛选 idToken 中的声明。 |
HTTP 触发器的绑定表达式
SignalR 输入绑定的某些属性的值通常来自 HTTP 请求。 因此,我们将演示如何通过绑定表达式将 HTTP 请求中的值绑定到 SignalR 输入绑定属性。
HTTP 元数据类型 | 绑定表达式格式 | 说明 | 示例 |
---|---|---|---|
HTTP 请求查询 | {query.QUERY_PARAMETER_NAME} |
将相应查询参数的值绑定到属性 | {query.userName} |
HTTP 请求标头 | {headers.HEADER_NAME} |
将标头的值绑定到属性 | {headers.token} |