我目前正在尝试使用PrincipalContext类通过Active Directory服务进行身份验证。我想让我的应用程序使用密封和SSL上下文对域进行身份验证。为此,我必须使用the following constructor of PrincipalContext (link to MSDN page):
public PrincipalContext(
ContextType contextType,
string name,
string container,
ContextOptions options
)
具体来说,我正在使用构造函数:
PrincipalContext domainContext = new PrincipalContext(
ContextType.Domain,
domain,
container,
ContextOptions.Sealing | ContextOptions.SecureSocketLayer);
MSDN说“容器”:
商店中的容器用作 上下文的根源。所有查询 在这个根下执行,所有 插入执行到此 容器。对于域和 ApplicationDirectory上下文类型, 这个参数是尊贵的 容器对象的名称(DN)。
容器对象的DN是多少?如何找出容器对象是什么?我可以查询Active Directory(或LDAP)服务器吗?
答案 0 :(得分:30)
好吧,我设法找出了问题:
PrincipalContext domainContext = new PrincipalContext(ContextType.Domain,domain);
domainContext.ValidateCredentials(userName, password,
ContextOptions.Negotiate | ContextOptions.SecureSocketLayer);
通过在ValidateCredentials方法中指定ContextOptions(而不是在构造函数中),这使我可以避免必须为容器对象指定DN。
<强>更新强>
虽然我应该澄清一下,经过进一步的实验,我发现从这个PrincipalContext对象派生的任何查询都是经过UN加密的。
显然,当在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 :(得分:0)
可以将容器设置为域的DC
部分。
corp.contoso.com
=> var container = "DC=corp, DC=contoso, DC=com"