【问题标题】:Given user id, password, and a subdomain name, how can I obtain the top-level domain name for a user account?给定用户名、密码和子域名,如何获取用户帐户的顶级域名?
【发布时间】:2018-05-03 15:31:02
【问题描述】:

我正在编写一个在Win 7 客户端机器上运行的程序(WinFormsC#)。它从用户那里获取凭据(用户 ID、密码和子域名),并使用它们向程序远程连接的其他服务器进行身份验证(通过Active Directory)。其他服务器所在的域与Win 7 客户端计算机所在的域不同。

使用 NetworkCredentialLdapDirectoryIdentifierLdapConnection 类,我可以使用不超过用户 ID、密码和子域名的凭据来测试凭据(请参阅 S.O.Why does Active Directory validate last password? 的答案)。

例如,对于用户帐户ssmith@xyz.gov,我只需提供ssmith(用户ID)、ssmith 的密码和xyzsubdomain)。我不需要提供top-level domain name(在这种情况下为gov)。

现在,我想以编程方式获取此用户帐户的top-level domain name(在本例中为gov)。我检查了NetworkCredentialLdapDirectoryIdentifierLdapConnection 类的属性和方法。我查看了System.DirectoryServices.Protocols Namespace 中的其他类。我没有看到以编程方式获取top-level domain name 的方法。

给定user idpasswordsubdomain 名称,我如何获取用户帐户的top-level domain name

这是我的代码。给定 ssmith@xyz.gov 的用户帐户,我的调用如下所示(星号表示 SecureString 密码)

bool result = ValidateCredentials("ssmith","******", "xyz");

这是我的方法代码。

private const int ERROR_LOGON_FAILURE = 0x31;

private bool ValidateCredentials(string username, SecureString ssPassword, string domain)
{

    //suports secure string 
    NetworkCredential credentials = new NetworkCredential(username, ssPassword, domain);

    LdapDirectoryIdentifier id = new LdapDirectoryIdentifier(domain);

    using (LdapConnection connection = new LdapConnection(id, credentials, AuthType.Kerberos))
    {
        connection.SessionOptions.Sealing = true;
        connection.SessionOptions.Signing = true;

        try
        {
            // The only way to test credentials on a LDAP connection seems to be to attempt a 
            // Bind operation, which will throw an exception if the credentials are bad
            connection.Bind();
        }
        catch (LdapException lEx)
        {
            credentials = null;
            id = null;

            if (ERROR_LOGON_FAILURE == lEx.ErrorCode)
            {
                return false;
            }

            throw;
        }
    }

    credentials = null;
    id = null;

    return true;
}

【问题讨论】:

  • 如果您还不知道域,您的LdapDirectoryIdentifier 对象声明是什么样的?
  • @GabrielLuci:我为调用我的方法和方法添加了代码。请看上面。用户将知道子域xyz,但可能不知道顶级域gov。而且,LdapDirectoryIdentifier 在这种情况下显然不需要顶级域
  • 那么domain变量不是已经包含顶级域的名称了吗?
  • 没有。只是子域名。详细信息在我的问题中
  • 我明白了。您正在使用域的简称。

标签: c# winforms active-directory ldap domain-name


【解决方案1】:

绑定成功后,域名的完整DNS名称将在LdapConnection对象中:

var domain = connection.SessionOptions.DomainName;

在这种情况下,这将是“xyz.gov”。如果您只需要“gov”,那么您可以只取最后一个点之后的所有内容:

var tld = domain.Substring(domain.LastIndexOf('.') + 1);

【讨论】:

  • "绑定成功后"。谢谢 - 我没有想到在成功绑定之后查看我的 connection 对象 :-(
  • .co.uk 域名等情况下,仅搜索最后一个点会非常糟糕。根据需要,您可以选择在第一个点上分割。
  • 我想我可以修改方法的签名以将完全限定的域名传回:private bool ValidateCredentials(string username, SecureString ssPassword, string domain, out string fqdn)。请参阅:“out 关键字导致参数通过引用传递。”。 out parameter modifier (C# Reference)
  • 或者,如果您使用的是最新的 Visual Studio,您可以使用 C# 7 的新功能 returning multiple valuesprivate (bool, string) ValidateCredentials(...) 然后 return (true, domainName);
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-07
相关资源
最近更新 更多