如何从 C# 中的显示名称获取 Active Directory 中的用户名?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9845444/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get a username in Active Directory from a display name in C#?
提问by JF Beaulieu
I want to be able to obtain the userid of a user in Active Directory using the display name of that user. The display name is obtained from a database, and has been stored during that user's session using the following code to obtain the display name:
我希望能够使用该用户的显示名称在 Active Directory 中获取该用户的用户 ID。显示名称是从数据库中获取的,并在该用户的会话期间使用以下代码存储以获取显示名称:
using System.DirectoryServices.AccountManagement;
private string GetDisplayName()
{
// set up domain context
PrincipalContext ctx = new PrincipalContext(ContextType.Domain);
// find currently logged in user
UserPrincipal user = UserPrincipal.Current;
return user.DisplayName;
}
This time around, I would like to have a method named GetUserIdFromDisplayName()that returns the Active Directory login name. Any ideas?
这一次,我想要一个名为的方法GetUserIdFromDisplayName()返回 Active Directory 登录名。有任何想法吗?
采纳答案by marc_s
I believe you can do it much more easily than with David's answer by using the built-in functionality of the System.DirectoryServices.AccountManagement(S.DS.AM) namespace.
我相信通过使用System.DirectoryServices.AccountManagement(S.DS.AM) 命名空间的内置功能,您可以比使用 David 的答案更容易地做到这一点。
Basically, you can define a domain context and easily find users and/or groups in AD:
基本上,您可以定义域上下文并轻松找到 AD 中的用户和/或组:
using System.DirectoryServices.AccountManagement;
private string GetUserIdFromDisplayName(string displayName)
{
// set up domain context
using(PrincipalContext ctx = new PrincipalContext(ContextType.Domain))
{
// find user by display name
UserPrincipal user = UserPrincipal.FindByIdentity(ctx, displayName);
//
if (user != null)
{
return user.SamAccountName;
// or maybe you need user.UserPrincipalName;
}
else
{
return string.Empty;
}
}
}
I don't see any need to go to the underlying DirectoryEntryobject, really - unless none of the properties of the UserPrincipalreally are what you're looking for.
我认为没有必要访问底层DirectoryEntry对象,真的 - 除非UserPrincipal你正在寻找的属性都不是真正的。
PS: if the search by display name shouldn't work (I don't have an AD at hand to test it right now) - you can always also use the PrincipalSearcherto find your user:
PS:如果按显示名称搜索不起作用(我现在手头没有广告来测试它)-您也可以随时使用PrincipalSearcher来查找您的用户:
using System.DirectoryServices.AccountManagement;
private string GetUserIdFromDisplayName(string displayName)
{
// set up domain context
using(PrincipalContext ctx = new PrincipalContext(ContextType.Domain))
{
// define a "query-by-example" principal - here, we search for a UserPrincipal
// and with the display name passed in
UserPrincipal qbeUser = new UserPrincipal(ctx);
qbeUser.DisplayName = displayName;
// create your principal searcher passing in the QBE principal
PrincipalSearcher srch = new PrincipalSearcher(qbeUser);
// find match - if exists
UserPrincipal user = srch.FindOne() as UserPrincipal;
if (user != null)
{
return user.SamAccountName;
// or maybe you need user.UserPrincipalName;
}
else
{
return string.Empty;
}
}
}
回答by David
UserPrincipalhas a method GetUnderlyingObject()which will return the DirectoryEntry.
UserPrincipal有一个方法GetUnderlyingObject()可以返回DirectoryEntry.
Get DirectoryEntry from Principal:
从主体获取 DirectoryEntry:
private DirectoryEntry GetDirectoryEntryFromUserPrincipal(Principal user)
{
return (DirectoryEntry)user.GetUnderlyingObject();
}
Get DirectoryEntry from domain and account name:
从域和帐户名获取 DirectoryEntry:
private DirectoryEntry GetDirectoryEntryFromDomainAndUsername(string domainName, string userName)
{
// Get the sid from the NT account name
var sid = (SecurityIdentifier) new NTAccount(domainName, accountName)
.Translate(typeof(SecurityIdentifier));
// Get the directory entry for the LDAP service account
var serviceEntry = new DirectoryEntry("LDAP://{address}", "serviceUsername", "servicePassword");
var mySearcher = new DirectorySearcher(serviceEntry)
{
Filter = string.Format("(&(ObjectSid={0}))", sid.Value)
};
return mySearcher.FindOne().GetDirectoryEntry();
}
Once you have the DirectoryEntryuse the Guidproperty to get the entry's Object-Guid
一旦您DirectoryEntry使用该Guid属性来获取条目的Object-Guid
private Guid GetObjectGuidFromDirectoryEntry(DirectoryEntry entry)
{
// return the Guid this is the Object-Guid (ignore NativeGuid)
return entry.Guid;
}
For tracking a user account in the application against a directory account: always use the Object-Guid as "This value is set when the object is created and cannot be changed."
NT and SAM account names can change if the user changes domains or, more commonly, changes their name (marriage, legal name-change, etc.) and should not be used to track a user.
要根据目录帐户跟踪应用程序中的用户帐户:始终使用 Object-Guid 作为“该值在创建对象时设置且无法更改”。
如果用户更改域或更常见的更改其姓名(婚姻、合法名称更改等),NT 和 SAM 帐户名称可能会更改,并且不应用于跟踪用户。
To get the NT account name (domain\username):
要获取 NT 帐户名(域\用户名):
private string GetNTAccountNameFromDirectoryEntry(DirectoryEntry entry)
{
PropertyValueCollection propertyValueCollection = entry.Properties["objectsid"];
SecurityIdentifier sid = new SecurityIdentifier((byte[]) propertyValueCollection[0], 0);
NTAccount ntAccount = (NTAccount)sid.Translate(typeof (NTAccount));
return account.ToString();
}
To get the SAM-Account-Name (username@domain):
获取 SAM-Account-Name (username@domain):
private string GetSAMAccountFromDirectoryEntry(DirectoryEntry entry)
{
return entry.Properties["Name"].Value;
}
And here's the exhaustive listof all the Active Directory attributes. Use the "Ldap-Display-Name" when getting the value from Properties
e.g. Properties["Ldap-Display-Name"]
这是所有 Active Directory 属性的详尽列表。从Properties
例如获取值时使用“Ldap-Display-Name”Properties["Ldap-Display-Name"]
Display-Name(FirstName MI LastName) might come in handy.
Display-Name(FirstName MI LastName) 可能会派上用场。

