从 Principal 而不是 DirectorySearcher 的 SearchResult 获取额外的 Active directory 属性
Get additional Active directory attributes from Principal instead of DirectorySearcher's SearchResult
我想从 AD 用户那里获得一些额外的 AD 属性。我想使用 PrincipalSearcher
而不是 DirectorySearcher
。
我所做的是获取 PrincipalSearcher 的 underlyingSearcher 并调用 FindOne() 方法。我不喜欢使用 PrincipalSearcher 中的 GetUnderlyingSearcher,但显然它有效。
代码有效,但我想知道是否有办法从 Principal
中读取额外的 properties/Ad 属性
Principal match = principalSearcher.FindOne();
另外,下面的代码可能有一些问题,因为我们正在使用 underlyingSearcher (DirectorySearcher) 方法。
我发现 PrincipalSearcher
更高级别,而且如果我要使用 DirectorySearcher,则必须定义 ldapPath e.g. var ldapPath = "DC=corp,DC=ad,DC=example,DC=com";
它只是代码行数更少。
public AdSimpleObject GetUser(string userName, string domainName)
{
PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, domainName);
UserPrincipal userPrincipal = new UserPrincipal(principalContext);
userPrincipal.SamAccountName = userName; // where condition
using (PrincipalSearcher principalSearcher = new PrincipalSearcher(userPrincipal))
{
using (DirectorySearcher ds = (DirectorySearcher)principalSearcher.GetUnderlyingSearcher())
{
// get only properties we need, therefore search performance is increased
ds.PropertiesToLoad.Clear();
ds.PropertiesToLoad.AddRange(new string[]
{
"sAMAccountType",
"sAMAccountName",
"userPrincipalName",
"msDS-PrincipalName"
});
SearchResult match = ds.FindOne();
if (match != null)
{
AdSimpleObject ado = this.CreateAdSimpleObject(match);
return ado;
}
return null;
}
}
}
public class AdSimpleObject
{
public string AdsPath { get; set; }
public int SamAccountType { get; set; }
public string SamAccountName { get; set; }
public string MsDsPrincipalName { get; set; }
public string UserPrincipalName { get; set; }
}
private AdSimpleObject CreateAdSimpleObject(SearchResult searchItem)
{
ResultPropertyCollection props = searchItem.Properties;
string adsPath = props["adspath"]?.OfType<string>().ToList().FirstOrDefault() ?? string.Empty;
int samAccountType = props["sAMAccountType"]?.OfType<int>().ToList().FirstOrDefault() ?? 0;
string samAccountName = props["sAMAccountName"]?.OfType<string>().ToList().FirstOrDefault() ?? string.Empty;
string userPrincipalName = props["userPrincipalName"]?.OfType<string>().ToList().FirstOrDefault() ?? string.Empty;
string msDsPrincipalName = props["msDS-PrincipalName"]?.OfType<string>().ToList().FirstOrDefault() ?? string.Empty;
return new AdSimpleObject
{
AdsPath = adsPath,
SamAccountType = samAccountType,
SamAccountName = samAccountName,
UserPrincipalName = userPrincipalName,
MsDsPrincipalName = msDsPrincipalName
};
}
I'm wondering if there is a way to read additional properties/Ad attributes from Principal
您将使用 DirectoryEntry
object returned from Principal.GetUnderlyingObject
:
Principal match = principalSearcher.FindOne();
var de = (DirectoryEntry) match.GetUnderlyingObject();
de.RefreshCache(new string[] {"someAttribute"});
var someAttribute = de.Properties["someAttribute"].Value;
这样做将返回到 AD 以获取属性,而不是使用在搜索中检索到的数据。 RefreshCache
的使用是告诉它只获取你感兴趣的属性。否则,如果你马上使用DirectoryEntry.Properties
,它会出去到AD并获取所有属性有一个值,这不太可能是你需要的,而且会无缘无故地花费额外的时间。
Additionally could below code have some problems because we are using the underlyingSearcher (DirectorySearcher) methods.
完全没有。该代码与制作您自己的 DirectorySearcher
并使用它没有什么不同。事实上,按照您编写这段代码的方式,根本没有必要使用 UserPrincipal
/PrincipalSearcher
。它为您做的唯一一件事就是构建查询字符串。
整个 AccountManagement
命名空间只是 DirectoryEntry
/DirectorySearcher
的包装器。它使程序员的事情变得更容易(在某些情况下,并非全部),但这样做是以牺牲性能为代价的。
如果您自己直接使用 DirectoryEntry
/DirectorySearcher
,您可以更好地控制从 AD 检索的数据量以及网络请求的频率。这些转化为更少的时间。如果您只是搜索一个帐户,那么它不会有太大的不同。但是,如果您要搜索大量用户,或者遍历大量用户列表,则效果会大不相同。
我写了一篇关于在与 AD 交谈时优化性能的文章(特别是 DirectoryEntry
/DirectorySearcher
):Active Directory: Better performance
我想从 AD 用户那里获得一些额外的 AD 属性。我想使用 PrincipalSearcher
而不是 DirectorySearcher
。
我所做的是获取 PrincipalSearcher 的 underlyingSearcher 并调用 FindOne() 方法。我不喜欢使用 PrincipalSearcher 中的 GetUnderlyingSearcher,但显然它有效。
代码有效,但我想知道是否有办法从 Principal
Principal match = principalSearcher.FindOne();
另外,下面的代码可能有一些问题,因为我们正在使用 underlyingSearcher (DirectorySearcher) 方法。
我发现 PrincipalSearcher
更高级别,而且如果我要使用 DirectorySearcher,则必须定义 ldapPath e.g. var ldapPath = "DC=corp,DC=ad,DC=example,DC=com";
它只是代码行数更少。
public AdSimpleObject GetUser(string userName, string domainName)
{
PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, domainName);
UserPrincipal userPrincipal = new UserPrincipal(principalContext);
userPrincipal.SamAccountName = userName; // where condition
using (PrincipalSearcher principalSearcher = new PrincipalSearcher(userPrincipal))
{
using (DirectorySearcher ds = (DirectorySearcher)principalSearcher.GetUnderlyingSearcher())
{
// get only properties we need, therefore search performance is increased
ds.PropertiesToLoad.Clear();
ds.PropertiesToLoad.AddRange(new string[]
{
"sAMAccountType",
"sAMAccountName",
"userPrincipalName",
"msDS-PrincipalName"
});
SearchResult match = ds.FindOne();
if (match != null)
{
AdSimpleObject ado = this.CreateAdSimpleObject(match);
return ado;
}
return null;
}
}
}
public class AdSimpleObject
{
public string AdsPath { get; set; }
public int SamAccountType { get; set; }
public string SamAccountName { get; set; }
public string MsDsPrincipalName { get; set; }
public string UserPrincipalName { get; set; }
}
private AdSimpleObject CreateAdSimpleObject(SearchResult searchItem)
{
ResultPropertyCollection props = searchItem.Properties;
string adsPath = props["adspath"]?.OfType<string>().ToList().FirstOrDefault() ?? string.Empty;
int samAccountType = props["sAMAccountType"]?.OfType<int>().ToList().FirstOrDefault() ?? 0;
string samAccountName = props["sAMAccountName"]?.OfType<string>().ToList().FirstOrDefault() ?? string.Empty;
string userPrincipalName = props["userPrincipalName"]?.OfType<string>().ToList().FirstOrDefault() ?? string.Empty;
string msDsPrincipalName = props["msDS-PrincipalName"]?.OfType<string>().ToList().FirstOrDefault() ?? string.Empty;
return new AdSimpleObject
{
AdsPath = adsPath,
SamAccountType = samAccountType,
SamAccountName = samAccountName,
UserPrincipalName = userPrincipalName,
MsDsPrincipalName = msDsPrincipalName
};
}
I'm wondering if there is a way to read additional properties/Ad attributes from
Principal
您将使用 DirectoryEntry
object returned from Principal.GetUnderlyingObject
:
Principal match = principalSearcher.FindOne();
var de = (DirectoryEntry) match.GetUnderlyingObject();
de.RefreshCache(new string[] {"someAttribute"});
var someAttribute = de.Properties["someAttribute"].Value;
这样做将返回到 AD 以获取属性,而不是使用在搜索中检索到的数据。 RefreshCache
的使用是告诉它只获取你感兴趣的属性。否则,如果你马上使用DirectoryEntry.Properties
,它会出去到AD并获取所有属性有一个值,这不太可能是你需要的,而且会无缘无故地花费额外的时间。
Additionally could below code have some problems because we are using the underlyingSearcher (DirectorySearcher) methods.
完全没有。该代码与制作您自己的 DirectorySearcher
并使用它没有什么不同。事实上,按照您编写这段代码的方式,根本没有必要使用 UserPrincipal
/PrincipalSearcher
。它为您做的唯一一件事就是构建查询字符串。
整个 AccountManagement
命名空间只是 DirectoryEntry
/DirectorySearcher
的包装器。它使程序员的事情变得更容易(在某些情况下,并非全部),但这样做是以牺牲性能为代价的。
如果您自己直接使用 DirectoryEntry
/DirectorySearcher
,您可以更好地控制从 AD 检索的数据量以及网络请求的频率。这些转化为更少的时间。如果您只是搜索一个帐户,那么它不会有太大的不同。但是,如果您要搜索大量用户,或者遍历大量用户列表,则效果会大不相同。
我写了一篇关于在与 AD 交谈时优化性能的文章(特别是 DirectoryEntry
/DirectorySearcher
):Active Directory: Better performance