如何在 .NET Web 应用程序中为经过身份验证的用户获取 UPN,而不查询 Active Directory

Posted

技术标签:

【中文标题】如何在 .NET Web 应用程序中为经过身份验证的用户获取 UPN,而不查询 Active Directory【英文标题】:How to get UPN for authenticated user in .NET web application, without querying Active Directory 【发布时间】:2012-06-08 09:22:24 【问题描述】:

(这个问题类似于Get UPN or email for logged in user in a .NET web application,但不完全一样。)

在使用 Windows 身份验证的 .NET (C#) Web 应用程序中,我想查找已登录用户的 UPN。

我知道如何通过查询 Active Directory 来做到这一点:从 HttpContext.Current.User.Identity as WindowsIdentity 获取 'DOMAINNAME\userName';在ldap://RootDSE 下查找DOMAINNAME 并找到它的dnsRoot;在ldap://...dnsRoot...下查询(&(objectCategory=person)(objectClass=user)(sAMAccountName=...userName...));获取此条目的 userPrincipalName 属性。 (更详细的答案在https://***.com/a/513668/223837)。

我的问题:可以调用 Active Directory 的情况下找到 UPN?鉴于 Microsoft 专注于在任何地方使用 UPN,UPN 是否已经存储在用户向 Web 服务器进行身份验证时创建的令牌中的某个位置?

(支持观察:如果我在 Windows 7 上运行 whoami /upn,那么 Wireshark 不会显示任何 Active Directory 连接。)

(如果有任何区别:请注意,我们的网络应用程序确实不使用模拟,即我们的网络应用程序不会以用户身份运行。)

【问题讨论】:

【参考方案1】:

尝试System.DirectoryServices.AccountManagement.UserPrincipal.Current,它具有UserPrincipalName 属性。当然,这需要应用程序在 Windows 身份验证下运行。

编辑嗯,看起来这个 API 仍在执行目录查找。

【讨论】:

嗯,至少这没有任何显式 AD 查询,这从我们的代码中消除了与AD 相关的复杂性。但是,我想知道这是否也适用于我们的 非模拟 .NET 应用程序:UserPrincipal.Current 是否包含 Web 应用程序的身份或经过身份验证的用户的身份?不幸的是,文档建议前者:“获取一个用户主体对象,该对象代表线程正在运行的当前用户。” 是的,它获得了 windows 身份,如果您不使用 windows 和集成身份验证或模拟,这将是应用程序池的身份。使用上下文查看 constrictor 的文档:它允许您填写所需用户的详细信息,然后为您查询和加载详细信息。正如您所说,为您自己节省了 LDAP 查询的复杂性。 new UserPrincipal(context, ...) 似乎对我没有帮助,因为我需要知道用户的密码。但是,临时冒充似乎可行:var wi = HttpContext.Current.User.Identity as WindowsIdentity; using (wi.Impersonate()) upn = UserPrincipal.Current.UserPrincipalName; 我仍然需要尝试一下。 我不会再尝试这个了,但是使用WindowsIdentity.Impersonate() 加上UserPrincipal.Current.UserPrincipalName 应该可以。我将此标记为答案。【参考方案2】:

我在使用 System.DirectoryServices.AccountManagement.UserPrincipal.Current 时遇到了 Active Directory 查询问题,因此我采用了 GetUserNameExNameUserPrincipal 格式。

此函数获取有关当前用户的信息,因此如果您还没有模拟,它确实需要您模拟。在 C# 中可以通过导入函数来完成:

public enum EXTENDED_NAME_FORMAT

    NameUnknown = 0,
    NameFullyQualifiedDN = 1,
    NameSamCompatible = 2,
    NameDisplay = 3,
    NameUniqueId = 6,
    NameCanonical = 7,
    NameUserPrincipal = 8,
    NameCanonicalEx = 9,
    NameServicePrincipal = 10,
    NameDnsDomain = 12


[DllImport("secur32.dll", CharSet = CharSet.Auto)]
public static extern int GetUserNameEx(int nameFormat, StringBuilder userName, ref int userNameSize);

然后这样称呼它:

string upn = null;
StringBuilder userName = new StringBuilder(1024);
int userNameSize = userName.Capacity;
if (GetUserNameEx((int)EXTENDED_NAME_FORMAT.NameUserPrincipal, userName, ref userNameSize) != 0)

    upn = userName.ToString();

【讨论】:

以上是关于如何在 .NET Web 应用程序中为经过身份验证的用户获取 UPN,而不查询 Active Directory的主要内容,如果未能解决你的问题,请参考以下文章

我如何通过 .net 远程调用模拟经过 Windows 身份验证的 Web 用户?

如何在 ASP.Net Web API 中为特定控制器启用 Windows 身份验证

在 NET 5 asp.net 核心 Web 应用程序中为 Kestrel 启用 Windows 身份验证

ASP.NET Core Web API 身份验证

如何在 Lotus Domino 中为不同的数据库设置不同的 Web 身份验证模式

如何在 .NET Core 中对 Spotify 进行经过身份验证的调用