我正在开发一个供内部组织使用的 Blazor 服务器应用程序。其中包括具有 Azure AD 的 Azure 租户、Azure 应用服务上托管的应用、应用注册...我想说没什么特别的。
我从 Azure ID 获取身份令牌以进行身份验证和授权。
在
Manage->Token configuration
下的应用程序注册中,我添加了 family_name
和 given_name
的可选声明。
我可以在本地主机上使用如下代码进行测试时读取它们:
user.FindFirst(ClaimTypes.GivenName)?.Value;
// ClaimTypes.GivenName is shorthand for:
// "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"
部署在 Azure 应用服务上时,此代码返回
null
。必须通过以下方式访问预期值:
user.FindFirst("given_name")?.Value;
这在本地主机上不起作用...
我还注意到,索赔名称之间甚至索赔数量之间也存在进一步的差异。
我希望声明标识符具有相同的名称,但根本不明白为什么会有差异。
有人可以详细说明一下吗?
谢谢
Edit:
我得到了一切正常的令牌,但是当在
key, value
中列出 user.Claims
对时,我得到了这个:
localhost:
(key: value)
[...]
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname": "Marty",
"http://schemas.microsoft.com/ws/2008/06/identity/claims/role": "Admin",
[...]
App Service:
[...]
"given_name": "Marty",
"roles": "Admin",
[...]
基本上,在 C# 类
ClaimTypes.[...]
中定义并使用长 hhtp://schemas.microsoft...
格式的所有 ClaimType 在部署时都会替换为较短的名称,而本地主机应用程序会使用较长的名称来替换它们。
您在 localhost 和 Azure 应用服务之间的声明名称中观察到的差异可能是由于不同环境中的底层身份验证库序列化和处理令牌声明的方式造成的。
在本地 (localhost) 运行 Blazor 服务器应用程序时,您可能会使用完整的声明类型名称(例如,
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"
),因为这是开发环境的默认行为或配置。
但是,当您的应用程序部署到 Azure 应用服务时,令牌声明可能会标准化为更简洁的格式,例如
"given_name"
。这种标准化通常用于提高令牌紧凑性并减少传输过程中的冗余。
为了确保代码的一致性,您可以使用常量或众所周知的字符串作为声明类型,无论您的应用程序是在本地运行还是在 Azure 应用服务环境中运行。
例如:
// Define constants for claim types
public static class CustomClaimTypes
{
public const string GivenName = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname";
public const string Role = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role";
}
// Usage
var givenName = user.FindFirst(CustomClaimTypes.GivenName)?.Value;
var role = user.FindFirst(CustomClaimTypes.Role)?.Value;
这样,您的代码在不同环境中保持一致,并且您可以使用您定义的常量处理声明类型,无论声明类型是以完整格式还是缩写格式呈现。
总而言之,您看到的差异可能与声明名称的规范化有关,并且在代码中使用常量或众所周知的字符串作为声明类型可以帮助保持跨环境的一致性。
您可以参考MSDocs