如何在不查询Active Directory的情况下为.NET web应用程序中经过身份验证的用户获取UPN

如何在不查询Active Directory的情况下为.NET web应用程序中经过身份验证的用户获取UPN,.net,active-directory,upn,.net,Active Directory,Upn,(这个问题类似于,但不完全相同。) 在使用Windows身份验证的.NET(C#)web应用程序中,我希望找到已登录用户的UPN 我知道如何通过查询Active Directory来做到这一点:将HttpContext.Current.User.Identity中的'DOMAINNAME\userName'作为WindowsIdentity;在ldap://RootDSE并找到它的dnsRoot;查询(&(objectCategory=person)(objectClass=user)(sAMA

(这个问题类似于,但不完全相同。)

在使用Windows身份验证的.NET(C#)web应用程序中,我希望找到已登录用户的UPN

我知道如何通过查询Active Directory来做到这一点:将
HttpContext.Current.User.Identity中的'DOMAINNAME\userName'作为WindowsIdentity
;在
ldap://RootDSE
并找到它的
dnsRoot
;查询
(&(objectCategory=person)(objectClass=user)(sAMAccountName=…userName…)
下的
ldap://...dnsRoot...
;获取此条目的
userPrincipalName
属性。(更多细节见答案)

我的问题:不调用Active Directory就可以找到UPN吗?鉴于微软专注于在任何地方使用UPN,UPN不是已经存储在用户向web服务器进行身份验证时创建的令牌中的某个地方了吗

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

(如果有任何区别:请注意,我们的web应用程序不使用模拟,即我们的web应用程序不在用户身份下运行。)

Try,其属性为
UserPrincipalName
。当然,这需要应用程序在Windows身份验证下运行


EditMeh,看起来此API仍在执行目录查找。

在使用
System.DirectoryServices.AccountManagement.UserPrincipal.Current
时,我对Active directory查询有问题,因此我采用了
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应用程序:
UserPrincipal.Current
是否包含web应用程序的身份,或者是经过身份验证的用户的身份?不幸的是,文档建议使用前者:“获取一个用户主体对象,该对象表示线程正在运行的当前用户。”是的,它获取windows标识,如果您不使用windows和集成身份验证或模拟,这将是应用程序池的标识。使用上下文查看constrator的文档:它允许您填写所需用户的详细信息,然后为您查询和加载详细信息。正如您所说,您自己就可以节省LDAP查询的复杂性。
newuserprincipal(context,…)
似乎对我没有帮助,因为我需要知道用户的密码。但是,临时模拟似乎可以工作:
var wi=HttpContext.Current.User.Identity作为WindowsIdentity;使用(wi.Impersonate()){upn=UserPrincipal.Current.UserPrincipalName;}
我仍然需要尝试这个方法。我不再尝试这个方法,但是使用
WindowsIdentity.Impersonate()
plus
UserPrincipalName.Current.UserPrincipalName
应该可以。我把这个作为答案。