20

我目前正在尝试使用 PrincipalContext 类通过 Active Directory 服务进行身份验证。我想让我的应用程序使用 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 说关于“容器”:

商店中用作上下文根的容器。所有查询都在这个根目录下执行,所有插入都在这个容器中执行。对于 Domain 和 ApplicationDirectory 上下文类型,此参数是容器对象的专有名称 (DN)。

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

4

2 回答 2

31

好吧,我设法弄清楚了这个问题:

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 身份验证和查询,但这对我来说似乎很奇怪。

于 2010-03-29T18:41:58.113 回答
0

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

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

于 2020-03-02T09:21:06.920 回答