简短回答:当构造函数的path
参数DirectoryEntry
包含无效域名时,DirectoryEntry
对象将(在 forrest 中搜索无效域失败后)尝试通过删除username
参数的域部分并尝试使用普通用户名进行连接来回退(sAMAccountName)。
长答案:如果参数中指定的域名username
无效但用户存在于path
参数中指定的域中,则用户将通过身份验证(通过使用回退)。但是,如果用户存在于 forrest 中的另一个域中,而不是参数中指定的域,则只有在包含参数的域部分并且正确path
时,身份验证才会成功。username
在处理 DirectoryEntry 对象时,有四种不同的方式来指定用户名参数:
- 专有名称(CN=用户名,CN=用户,DC=域,DC=本地)
- NT 帐户名称(域\用户名)
- 普通账户名/sAMAccountname(用户名)
- 用户主体名称(通常为 username@domain.local)
让我用一个例子来说明:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.DirectoryServices;
namespace DirectoryTest
{
class Program
{
private static Int32 counter = 1;
static void Main(string[] args)
{
TestConnection();
}
private static void TestConnection()
{
String domainOne = "LDAP://DC=domain,DC=one";
String domainOneName = "DOMAINONE";
String domainOneUser = "onetest";
String domainOnePass = "testingONE!";
String domainTwo = "LDAP://DC=domain,DC=two";
String domainTwoName = "DOMAINTWO";
String domainTwoUser = "twotest";
String domainTwoPass = "testingTWO!";
String invalidDomain = "INVALIDDOMAIN";
// 1) This works because it's the correct NT Account Name in the same domain:
Connect(domainOne, domainOneName + "\\" + domainOneUser, domainOnePass);
// 2) This works because username can be supplied without the domain part
// (plain username = sAMAccountName):
Connect(domainOne, domainOneUser, domainOnePass);
// 3) This works because there's a fall back in DirectoryEntry to drop the domain part
// and attempt connection using the plain username (sAMAccountName) in (in this case)
// the forrest root domain:
Connect(domainOne, invalidDomain + "\\" + domainOneUser, domainOnePass);
// 4) This works because the forrest is searched for a domain matching domainTwoName:
Connect(domainOne, domainTwoName + "\\" + domainTwoUser, domainTwoPass);
// 5) This fails because domainTwoUser is not in the forrest root (domainOne)
// and because no domain was specified other domains are not searched:
Connect(domainOne, domainTwoUser, domainTwoPass);
// 6) This fails as well because the fallback of dropping the domain name and using
// the plain username fails (there's no domainTwoUser in domainOne):
Connect(domainOne, invalidDomain + "\\" + domainTwoUser, domainTwoPass);
// 7) This fails because there's no domainTwoUser in domainOneName:
Connect(domainOne, domainOneName + "\\" + domainTwoUser, domainTwoPass);
// 8) This works because there's a domainTwoUser in domainTwoName:
Connect(domainTwo, domainTwoName + "\\" + domainTwoUser, domainTwoPass);
// 9) This works because of the fallback to using plain username when connecting
// to domainTwo with an invalid domain name but using domainTwoUser/Pass:
Connect(domainTwo, invalidDomain + "\\" + domainTwoUser, domainTwoPass);
}
private static void Connect(String path, String username, String password)
{
Console.WriteLine(
"{0}) Path: {1} User: {2} Pass: {3}",
counter, path, username, password);
DirectoryEntry de = new DirectoryEntry(path, username, password);
try
{
de.RefreshCache();
Console.WriteLine("{0} = {1}", username, "Autenticated");
}
catch (Exception ex)
{
Console.WriteLine("{0} ({1})", ex.Message, username);
}
Console.WriteLine();
counter++;
}
}
}
在上面的示例中,domain.one 是 forrest 根域,domain.two 与 domain.one 位于同一 forrest 中(但自然是不同的树)。
因此,回答您的问题:如果用户不在我们要连接的域中并且在参数中未指定或指定无效域名,则身份验证将始终失败username
。