出于安全原因,服务器可能托管在独立于 Azure SignalR 服务资源的租户中。 由于托管标识不能跨租户使用,因此需要在租户 A 中注册应用程序,然后在租户 B 中将其预配为企业应用程序。本文介绍如何在租户 A 中创建应用程序,并使用它连接到租户 B 中的 Azure SignalR 服务资源。
在租户 A 中注册多租户应用程序
第一步是创建多租户应用程序。 有关详细信息,请参阅 快速入门:在 Microsoft Entra ID 中注册应用程序。
如果已有单个租户应用程序,请按照 Microsoft Entra ID 上的“将单租户应用转换为多租户”中的说明进行作。
有四种帐户类型:
- 此组织目录中的帐户
- 任何组织目录中的帐户
- 任何组织目录中的帐户和个人Microsoft帐户
- 个人Microsoft帐户
创建应用程序时,请务必选择第二种类型或第三种类型。
。
记下应用程序(客户端)ID 和目录(租户)ID,以便在以下步骤中使用。
在租户 B 中预配应用程序
不能将角色分配给在其他租户中注册的应用程序。 必须在租户 B 中将其预配为外部企业应用程序。如果需要更多信息,可以了解 应用注册和企业应用程序之间的差异。
简言之,企业应用程序是服务主体,应用注册不是。 企业应用程序从应用程序对象继承某些属性,例如应用程序(客户端)ID。
在注册应用的租户中创建默认服务主体。 对于其他租户,需要预配应用以获取企业应用程序服务主体。 有关详细信息,请参阅 Microsoft Entra ID 中的多租户应用程序创建企业应用程序。
不同租户中的企业应用程序具有不同的目录(租户)ID,但它们共享相同的应用程序(客户端)ID。
将角色分配给企业应用程序
在租户 B 中预配企业应用程序后,可以向其分配角色。
以下步骤介绍如何将 SignalR 应用服务器角色分配给 Azure SignalR 服务资源的服务主体或托管标识。 有关详细步骤,请参阅使用 Azure 门户分配 Azure 角色。
注释
可以将角色分配给任何范围,包括管理组、订阅、资源组或单个资源。 若要了解有关范围的详细信息,请参阅了解 Azure RBAC 的作用域。
在 Azure 门户中,转到你的 Azure SignalR 服务资源。
在左侧窗格中,选择访问控制 (IAM)。
选择添加>添加角色分配。
在“角色”选项卡上,选择“SignalR 应用服务器”。 其他 Azure SignalR 服务内置角色取决于你的方案。
角色 DESCRIPTION 用例 SignalR 应用服务器 访问创建服务器连接和生成密钥的 API。 最常用于在默认模式下运行 Azure SignalR 资源的应用服务器。 SignalR 服务所有者 完全访问所有数据平面 API,包括 REST API、创建服务器连接的 API 以及生成密钥/令牌的 API。 用于在“无服务器”模式下运行 Azure SignalR 服务资源的协商服务器。 它需要 REST API 权限和身份验证 API 权限。 SignalR REST API 所有者 对数据平面 REST API 的完全访问。 用于 Azure SignalR 管理 SDK 来管理连接和组,但它 不 进行服务器连接或处理协商请求。 SignalR REST API 读者 对数据平面 REST API 的只读访问。 编写调用只读 REST API 的监视工具时使用。 选择“下一步”。
对于 Microsoft Entra 应用程序:
- 在分配访问权限一行中,选择用户、组或服务主体。
- 在“成员”行中,选择“选择成员”,然后在弹出窗口中选择身份。
对于 Azure 资源的托管标识,请执行以下操作:
- 在“将访问权限分配给”行中,选择“托管标识”。
- 在“ 成员 ”行中, 选择成员,然后在弹出窗口中选择应用程序。
选择“下一步”。
查看分配,然后选择 “查看 + 分配 ”以确认角色分配。
重要
新添加的角色分配可能需要长达 30 分钟的时间来进行传播。
若要详细了解如何分配和管理 Azure 角色,请参阅:
- 使用 Azure 门户分配 Azure 角色
- 使用 REST API 分配 Azure 角色
- 使用 Azure PowerShell 分配 Azure 角色
- 使用 Azure CLI 分配 Azure 角色
- 使用 Azure 资源管理器模板分配 Azure 角色
将 Azure SignalR 服务 SDK 配置为使用企业应用程序
应用程序使用三种不同类型的凭据对自身进行身份验证:
- 证书
- 客户端机密
- 联合标识
我们强烈建议您使用证书或客户端密钥来执行跨租户请求。
使用证书或客户端机密
- 参数
tenantId
是租户 B 的 ID。 - 在这两个租户中,
clientId
参数是相等的。 - 租户 A 中配置了参数
clientSecret
和clientCert
参数。有关详细信息,请参阅 “添加凭据”。
如果不确定租户 ID,请参阅 “查找Microsoft Entra 租户”。
services.AddSignalR().AddAzureSignalR(option =>
{
var credential1 = new ClientSecretCredential("tenantId", "clientId", "clientSecret");
var credential2 = new ClientCertificateCredential("tenantId", "clientId", "path-to-cert");
option.Endpoints = new ServiceEndpoint[]
{
new ServiceEndpoint(new Uri("https://<resource1>.service.signalr.net"), credential1),
new ServiceEndpoint(new Uri("https://<resource2>.service.signalr.net"), credential2),
};
});
使用联合标识
出于安全原因,订阅中可能会禁用证书和客户端机密。 在这种情况下,您需要使用外部身份提供者,或者尝试托管身份的预览支持。 有关详细信息,请参见:
有关详细信息和视频指南,请参阅Microsoft Entra 跨租户应用程序联合标识凭据(FIC)。
将托管标识用作标识提供者时,代码如以下示例所示:
- 参数
tenantId
是租户 B 的 ID。 - 两个租户中的
clientId
参数相等。
services.AddSignalR().AddAzureSignalR(option =>
{
var msiCredential = new ManagedIdentityCredential("msiClientId");
var credential = new ClientAssertionCredential("tenantId", "appClientId", async (ctoken) =>
{
// Entra ID US Government: api://AzureADTokenExchangeUSGov
// Entra ID China operated by 21Vianet: api://AzureADTokenExchangeChina
var request = new TokenRequestContext([$"api://AzureADTokenExchange/.default"]);
var response = await msiCredential.GetTokenAsync(request, ctoken).ConfigureAwait(false);
return response.Token;
});
option.Endpoints = [
new ServiceEndpoint(new Uri(), "https://<resource>.service.signalr.net"), credential);
];
});
使用外部标识提供者时,代码如以下示例所示:
services.AddSignalR().AddAzureSignalR(option =>
{
var credential = new ClientAssertionCredential("tenantId", "appClientId", async (ctoken) =>
{
// Find your own way to get a token from the external identity provider.
// The audience of the token should be "api://AzureADTokenExchange" because it is the recommended value.
return "TheTokenYouGetFromYourExternalIdentityProvider";
});
option.Endpoints = [
new ServiceEndpoint(new Uri(), "https://<resource>.service.signalr.net"), credential);
];
});
使用 Azure SignalR 服务 SDK 调试令牌获取是一项挑战,因为它取决于令牌结果。 建议先在本地测试令牌获取过程,然后再与 Azure SignalR 服务 SDK 集成。
var assertion = new ClientAssertionCredential("tenantId", "appClientId", async (ctoken) =>
{
// Find your own way to get a token from the external identity provider.
// The audience of the token should be "api://AzureADTokenExchange" because it is the recommended value.
return TheTokenYouGetFromYourExternalIdentityProvider;
});
var request = new TokenRequestContext(["https://signalr.azure.com/.default");
var token = await assertion.GetTokenAsync(assertion);
Console.log(token.Token);
关键点是使用内部凭据从api://AzureADTokenExchange
或其他受信任的标识平台获取clientAssertion
参数。 然后使用它与 https://signalr.azure.com/.default
受众交换令牌来访问资源。
目标是获取具有以下声明的令牌。 使用 jwt.io 来帮助你解码令牌:
- oid:该值应等于企业应用程序对象 ID。 如果不知道在何处获取它,请参阅 “检索企业对象 ID”。
- tid:该值应等于租户 B 的目录 ID。如果不确定租户 ID,请参阅 “查找Microsoft Entra 租户”。
- 用户:用户必须是
https://signalr.azure.com/.default
才能访问 Azure SignalR 服务资源。