【问题标题】:Choose domain controller by IP address C#通过IP地址选择域控制器C#
【发布时间】:2016-01-18 19:42:28
【问题描述】:

以下是在 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 上创建它?或者有没有办法让所有 DC 上的帐户都可以进行复制?或强制帐户以编程方式复制(基于搜索 SO,我猜不是)。

【问题讨论】:

  • 我在工作中也自动创建了 AD 帐户。但我并没有为推动复制而烦恼。这可能比它的价值更多的工作。对我们来说,在 15 分钟内拥有一个可用的帐户比自动化之前的等待时间要好得多。
  • 是的,我们有公共站点,人们可以在其中注册、转身和登录。对于我们的员工来说,这完全没问题,因为我们在需要登录之前在雇用几天时创建了帐户。这是 on-需求帐户是问题。
  • 公共电台是否已经使用 AD 帐户(如通用访客帐户或其他)登录?如果是这样,您可以拉取 LOGONSERVER 环境变量,它会告诉您它已验证到哪个域控制器。
  • 我忘了提出这是信息亭上的网页的问题。因此,Web 服务器创建帐户,并且 LOGONSERVER env 变量将是我相信的 Web 服务器的登录服务器。
  • 是的,这让事情变得更难了。我进行了快速搜索,但找不到任何可靠的东西。如果您知道该站点,则可以确定最佳 DC,但我还没有找到将任何随机 IP 映射到最近站点的方法。

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


【解决方案1】:
            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);

这将为您提供与拓扑中最接近指定 IP 地址的站点和域关联的 DC。 然后将 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);
    }
}

【讨论】:

  • 太棒了。有一天我可能需要那个。
  • 我拒绝接受所有无法完成的现有堆栈溢出答案:)。
猜你喜欢
  • 1970-01-01
  • 2014-08-13
  • 2014-03-16
  • 2017-03-10
  • 2013-02-11
  • 2011-08-01
  • 1970-01-01
  • 2010-12-05
  • 1970-01-01
相关资源
最近更新 更多