Active Directory服务: PrincipalContext -- "容器"对象的DN是什么?

20

我目前正在尝试使用PrincipalContext类通过Active Directory Services进行身份验证。我希望我的应用程序使用Sealed和SSL上下文对域进行身份验证。为了实现这一点,我必须使用PrincipalContext的以下构造函数 (MSDN页面链接):

public PrincipalContext(
    ContextType contextType,
    string name,
    string container,
    ContextOptions options
)

具体来说,我是这样使用构造函数的:

PrincipalContext domainContext = new PrincipalContext(
    ContextType.Domain, 
    domain, 
    container, 
    ContextOptions.Sealing | ContextOptions.SecureSocketLayer);

MSDN关于"container"的解释:

用作上下文根的存储容器。所有查询均在此根下执行,并且所有插入均在此容器中执行。对于域和ApplicationDirectory上下文类型,该参数是容器对象的可区分名称(DN)。

什么是容器对象的DN?如何找到我的容器对象?可以查询Active Directory(或LDAP)服务器以获取此信息吗?

2个回答

32

好的,我成功地解决了这个问题:

PrincipalContext domainContext = new PrincipalContext(ContextType.Domain,domain);

domainContext.ValidateCredentials(userName, password, 
    ContextOptions.Negotiate | ContextOptions.SecureSocketLayer);

通过在ValidateCredentials方法中指定ContextOptions(而不是在构造函数中指定),这使我避免了必须为容器对象指定DN的情况。

更新:

尽管我应该澄清一下,经过进一步的实验,我发现从这个PrincipalContext对象派生的任何查询都是未加密的。

显然,当在ValidateCredentials中设置ContextOptions时,这些选项仅用于该特定ValidateCredentials调用。但这里就有点奇怪了...

因此,我希望我的AD服务器查询也能以加密方式进行。例如查询:

UserPrincipal p = UserPrincipal.FindByIdentity(
    domainContext, IdentityType.SamAccountName, userName);
var groups = p.GetGroups();
foreach (GroupPrincipal g in groups) { /* do something */ }

上述代码获取了用户所属的所有组的列表,但是这是在明文(未加密)下进行的。因此,经过一番尝试后,我发现 DN 永远不需要被设置。

PrincipalContext domainContext = new PrincipalContext(ContextType.Domain,domain,
    null,ContextOptions.Negotiate | ContextOptions.SecureSocketLayer);

我发现将容器对象(DN)设置为null是可行的。而且这样做运行良好。将其设置为空字符串("")会导致某些未知类型的异常,因此不要认为可以使用空字符串。

这里有一个奇怪的地方。你可能会认为在PrincipalContext中设置SecureSocketLayer选项意味着你不必在使用VerifyCredentials时显式设置它。但我发现如果我没有在VerifyCredentials部分设置它,身份验证将失败,但查询(如示例中的组)仍然以加密方式进行。

也许我还没有完全理解AD身份验证和查询,但这对我来说似乎是奇怪的行为。


1
您对于“奇怪的部分”的解释是修复调用ValidateCredentials时20秒延迟的关键。谢谢! - Brett Veenstra
我知道这已经很老了,但我正在研究是否使用SSL而不是签名,并偶然发现了这篇文章。我相信你可以在构造函数中使用null。当我想要指定ContextOptions时,我就是这样做的。例如:var pc = new PrincipalContext(ContextType.Domain, Environment.UserDomainName, null, ContextOptions.Sealing); - famousKaneis
@nameless: 我觉得这就是最后一个代码块中代码所展示的内容。(顺带一提,我几乎不记得这是关于什么的了,但当我弄清楚时,我感到非常高兴。) :) - Pretzel
@Pretzel 啊啊啊啊啊。很高兴听到这个消息,感谢您指出我没有完全阅读整篇答案的失误,哈哈。我在阅读到你的答案中“通过在ValidateCredentials中指定ContextOptions”部分时就停止了阅读。 - famousKaneis

0

容器可以设置为域中的 DC 部分。

corp.contoso.com => var container = "DC=corp, DC=contoso, DC=com"


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接