按IP地址C#选择域控制器

时间:2016-01-18 19:42:29

标签: c# asp.net active-directory user-accounts

以下是在AD中创建用户的简单代码。代码是DC非特定的。它不关心它创建它的DC,它将使用服务器连接的Windows默认值。

 using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, Domain, path, ContextOptions.Negotiate, ManagementUsername, ManagementPassword))
                {
                    try
                    {
                        using (UserPrincipal up = new UserPrincipal(pc, username, password, true))
                        {
                            up.GivenName = firstName; up.Surname = lastName; up.DisplayName = firstName + " " + lastName; up.UserPrincipalName = username + "@" + Domain; up.Save();
                        }
                    }
                    catch (PasswordException) { return null; }
                }

问题在于新帐户的复制时间(通常是域名有15分钟)。当想要在连接到与服务器不同的DC的工作站上使用该帐户的人请求帐户时,尝试实现按需帐户创建时,这不起作用。他们最终不得不坐在工作站前15分钟无法登录。

问题: 有没有办法连接到基于客户端IP地址的DC来创建它?或者有没有办法在所有DC上创建帐户并使复制正常?或者强制帐户以编程方式进行复制(基于搜索SO,我猜不是)。

1 个答案:

答案 0 :(得分:2)

            Forest adForest = Forest.GetCurrentForest();
            ActiveDirectorySite[] sites = new ActiveDirectorySite[adForest.Sites.Count];
            adForest.Sites.CopyTo(sites, 0);
            List<ActiveDirectorySubnet> subnets = new List<ActiveDirectorySubnet>();
            sites.ToList().ForEach(x =>
            {
                ActiveDirectorySubnet[] subnetTemp = new ActiveDirectorySubnet[x.Subnets.Count];
                x.Subnets.CopyTo(subnetTemp, 0);
                subnets.AddRange(subnetTemp);
            });
            IPAddress address = IPAddress.Parse("IPAddress to look up closest DC");
            var currentSubnet = subnets.Where(x => address.IsInRange(x.Name));
            var location = currentSubnet.First().Site.Name;

            DomainController dc = DomainController.FindOne(new DirectoryContext(DirectoryContextType.Domain, Domain), location);

这将使您获得与该站点和域相关联的DC,该站点和域最接近拓扑中的指定IP地址。 然后将DC IP地址传递给Principal Context。

              using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, dc.IPAddress, path, ContextOptions.Negotiate, ManagementUsername, ManagementPassword))
                {
                    try
                    {
                        using (UserPrincipal up = new UserPrincipal(pc, username, password, true))
                        {
                            up.GivenName = firstName; up.Surname = lastName; up.DisplayName = firstName + " " + lastName; up.UserPrincipalName = username + "@" + Domain; up.Save();
                        }
                    }
                    catch (PasswordException) { return null; }
                }

创建用户。

注意:IPAddress函数是通过github上的NetTools IPAddressRange类以及它的以下自定义扩展来完成的。

/// <summary>
/// All extensions for IPAddress type
/// </summary>
public static class IPAddressExtension
{
    /// <summary>
    /// Determine whether this IP address is part of the range/subnet
    /// </summary>
    /// <param name="range">A range of IPAddresses</param>
    /// <returns></returns>
    public static bool IsInRange(this IPAddress thisIP, IPAddressRange range)
    {
        return range.Contains(thisIP);
    }

    /// <summary>
    /// Determine whether this IP address is part of the range/subnet
    /// </summary>
    /// <param name="range">Can be specified in CIDR/UNI (ex: 192.168.10.0/24) </param>
    /// <returns></returns>
    public static bool IsInRange(this IPAddress thisIP, string rangeIP)
    {
        IPAddressRange range = IPAddressRange.Parse(rangeIP);
        return range.Contains(thisIP);
    }

    /// <summary>
    /// Determine whether this IP address is part of the range/subnet
    /// </summary>
    /// <param name="ipBegin">Beginning IP address of range</param>
    /// <param name="ipEnd">Ending IP address of range</param>
    /// <returns></returns>
    public static bool IsInRange(this IPAddress thisIP, IPAddress ipBegin, IPAddress ipEnd)
    {
        IPAddressRange range = new IPAddressRange(ipBegin, ipEnd);
        return range.Contains(thisIP);
    }
}