如何在 .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 查询问题,因此我采用了 GetUserNameEx
和 NameUserPrincipal
格式。
此函数获取有关当前用户的信息,因此如果您还没有模拟,它确实需要您模拟。在 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 身份验证