【问题标题】:How to find a User's Group with LDAP in C# Core 2如何在 C# Core 2 中使用 LDAP 查找用户组
【发布时间】:2017-10-27 08:31:21
【问题描述】:

我正在使用 C# Core 2,使用 Active Directory 作为 Novell 的身份验证方法 - 我已经根据密码部分验证用户,如果 AD 中的用户名和密码正确,则验证他们。

我想获取登录用户的用户组,以增加安全性,就像[Authorize(roles="*")]would 一样。

以下代码是我目前所拥有的,我知道连接是正确的,但我无法在 SearchResults 中得到任何结果,它总是以 0 的计数返回。

我哪里出错了?以前没有任何 Active Directory 暴露。

搜索功能:

    int searchScope = LdapConnection.SCOPE_BASE;
    string searchFilter = "(CN = " + username + ")";
    string searchBase = "OU=Users,OU=TOD,OU=Departments,DC=domain,DC=com";
    // folder structure Users/TOD/Departments/List of people

    // reading members of dynamic group could take long so set timeout to 10 seconds
    LdapSearchConstraints constraints = new LdapSearchConstraints();
    constraints.TimeLimit = 10000;

    #region connection
    string host = "mydomain.com";
    string un = "mydomain\\" + username;
    int port = 389;
    int version = LdapConnection.Ldap_V3;

    var conn = new LdapConnection();

    conn.SecureSocketLayer = false;
    conn.Connect(host, port);
    conn.Bind(version, un, pass); //parsed in through function params
    #endregion

    LdapSearchResults searchResults = conn.Search(
        searchBase,
        searchScope,
        searchFilter,
        null, // no specified attributes
        false, // return attr and value
        constraints);
      // always returns a search with 0 count

更新:

我间歇性地收到 LDAP 连接错误,并且在其他情况下,搜索返回为空 - 我不知道这是否与等待有关,但它会立即达到我在 conn.Disconnect() 设置的断点而不是比 while 循环中的任何断点都多。

[TestMethod]
    public void SearchForUserDepartentTest()
    {
        var users = new Dictionary<string,string>();
        var count = 0;

        string searchFilter = "(objectclass=*)";
        string searchBase = "OU=Departments,DC=domain,DC=com"; //ou=users, ou=TOD

        // reading members of dynamic group could take long so set timeout to 10 seconds
        LdapSearchConstraints constraints = new LdapSearchConstraints();
        constraints.TimeLimit = 10000;

        #region connection
        string host = "domain.com";
        string un = "domain\\doatemp2";
        string pass = "****";
        int port = 389;
        int version = LdapConnection.Ldap_V3;

        var conn = new LdapConnection
        {
            SecureSocketLayer = false
        };
        conn.Connect(host, port);
        conn.Bind(version, un, pass);
        #endregion
        try
        {
            LdapSearchResults searchResults = conn.Search(
                searchBase,
                LdapConnection.SCOPE_ONE,
                searchFilter,
                null, // no specified attributes
                false, // return attr and value
                constraints);

            while (searchResults.hasMore())
            {
            // doesn't hit in here intermittently
                count++;
                var nextEntry = searchResults.next();

                nextEntry.getAttributeSet();
                var attr = nextEntry.getAttribute("NAME");

                if (attr == null)
                {
                    users.Add("Distinguished Name", nextEntry.getAttribute("distinguishedName").StringValue);
                }
                else
                {
                    users.Add((nextEntry.getAttribute("SAMACCOUNTNAME") == null)? "NULL ACC Name " + count : nextEntry.getAttribute("SAMACCOUNTNAME").StringValue
                        ,(nextEntry.getAttribute("DISTINGUISHEDNAME") == null)? "NULL DN" + count : nextEntry.getAttribute("distinguishedName").StringValue);
                }                    
            }
        }
        catch (LdapException ldapEx)
        {
            ldapEx.ToString(); // ocassional time outs
        }
        catch (Exception ex)
        {
            ex.ToString();
        }
        conn.Disconnect(); // when run hits the break point here, missing out the anything in searchResults.hasMore()
    }

更新 2:

最新代码。

[TestMethod]
public void SearchForUserDepartentTest()
{ 
    var users = new Dictionary<string,string>();
    var count = 0;

    string searchFilter = "(objectclass=*)";
    string searchBase = "OU=Departments,DC=domain,DC=com"; //ou=users, ou=TOD

    // reading members of dynamic group could take long so set timeout to 10 seconds
    LdapSearchConstraints constraints = new LdapSearchConstraints();
    constraints.TimeLimit = 30000;

    #region connection information
    string host = "domain";
    string un = "domain\\doatemp2";
    string pass = "";
    int port = 389;
    int version = LdapConnection.Ldap_V3;
    #endregion

    try
    {
        using (var conn = new LdapConnection { SecureSocketLayer = false })
        {
            conn.Connect(host, port);
            conn.Bind(version, un, pass);

            LdapSearchResults searchResults = conn.Search(
                searchBase,
                LdapConnection.SCOPE_SUB,
                searchFilter,
                null, // no specified attributes
                false, // return attr and value
                constraints);

            while (searchResults.hasMore())
            {
                count++;
                var nextEntry = searchResults.next();

                nextEntry.getAttributeSet();
                var attr = nextEntry.getAttribute("NAME");

                if (attr == null)
                {
                    users.Add("Distinguished Name", nextEntry.getAttribute("distinguishedName").StringValue);
                }
                else
                {
                    users.Add((nextEntry.getAttribute("SAMACCOUNTNAME") == null) ? "NULL ACC Name " + count : nextEntry.getAttribute("SAMACCOUNTNAME").StringValue, 
                        (nextEntry.getAttribute("DISTINGUISHEDNAME") == null) ? "NULL DN" + count : nextEntry.getAttribute("distinguishedName").StringValue);
                }
            }
        }
    }
    catch (LdapException ldapEx)
    {
        ldapEx.ToString(); // ocassional time outs
    }
    catch (Exception ex)
    {
        ex.ToString();
    }

    var check = users;
}

更新 3: 在测试环境造成不利影响的情况下使用 Core 控制台应用程序。使用下面的代码读取 LdapConnection timeout 85

公共静态无效 SearchForUserDepartent() { var users = new Dictionary(); 变量计数 = 0;

string searchFilter = "(objectclass=*)";//string.Empty;
string searchBase = "OU=Users,OU=TOD,OU=Departments,DC=domain,DC=com";

LdapSearchConstraints constraints = new LdapSearchConstraints
{
    TimeLimit = 15000
};

#region connection information
string host = "dm1.domain.com";
string un = "domain\\doatemp2";
string pass = "password";
int port = 389;
#endregion

try
{
    using (var conn = new LdapConnection { SecureSocketLayer = false })
    {
        conn.Connect(host, port);
        conn.Bind(un, pass);

        LdapSearchResults searchResults = conn.Search(
            searchBase,
            LdapConnection.SCOPE_SUB,
            searchFilter,
            null, // no specified attributes
            false, // return attr and value
            constraints);

        while (searchResults.hasMore())
        {
            count++;
            var nextEntry = searchResults.next(); // hits and then goes to timeout

            nextEntry.getAttributeSet();
            Console.WriteLine("Distinguished Name:" + nextEntry.getAttribute("distinguishedName").StringValue);
            Console.ReadKey();
        }
    }
}
catch (LdapException ldapEx)
{
    Console.WriteLine(ldapEx.ToString()); // ocassional time outs
}
catch (Exception ex)
{
    Console.WriteLine(ex.ToString());
}
    foreach(var u in users)
    {
        Console.WriteLine("Key:" + u.Key.ToString() + " | Value:" + u.Value.ToString());
    }
Console.ReadKey();
}

【问题讨论】:

  • @Jaybird 这部分是我一直在使用的,但我在 searchResults 中什么也没得到,我认为我使用 searchBase、searchFilter 和/或 searchScope 不正确。
  • @PurpleSmurph,我忘了说。尝试使用 CN=Users,DC=domain,DC=com 或 CN=Users,OU=TOD,OU=Departments,DC=domain,DC=com

标签: c# asp.net-core active-directory ldap


【解决方案1】:

LdapSearchResults 计数始终为 0,您应该使用 .hasMore() 来获取搜索的价值

试试这样的想法

                var users = new HashSet<string>();
//My domain have 4 DC's
            LdapSearchResults searchResults = conn.Search(
                "CN=Users,DC=z,DC=x,DC=c,DC=v",//You can use String.Empty for all domain search. This is example about users
                LdapConnection.SCOPE_SUB,//Use SUB
                "(mail=*@somemail.com)",// Example of filtering with *. You can use String.Empty to query without filtering
                null, // no specified attributes
                false // return attr and value
                );

            while (searchResults.hasMore())
            {
                var nextEntry = searchResults.next();
                nextEntry.getAttributeSet();
                var attr = nextEntry.getAttribute("mail");

                if (attr == null)
                {
                    users.Add(nextEntry.getAttribute("distinguishedName").StringValue);
                }
                else {
                    users.Add(nextEntry.getAttribute("mail").StringValue);
                }

            }

为了更好地查询,请使用 ActiveDirectory 用户和计算机。有属性编辑器可以提供有关DC,CN,OU和attrs的所有信息

更多信息请访问herehere

更新:正如官方documentation 所说:

SCOPE_BASE:与搜索一起使用以指定条目的范围 search 是只搜索基础对象。

SCOPE_ONE:与搜索一起使用以指定条目的范围 search 是只搜索基础对象的直接下属。

SCOPE_SUB:与搜索一起使用以指定条目的范围 搜索是搜索基础对象及其中的所有条目 子树。

SCOPE_SUB 表示您可以使用 searchBase 没有完整的入口路径或使用 string.Empty 进行全域搜索

【讨论】:

  • 不完全是我所追求的,但绝对是正确的道路!谢谢。将更新您的答案,可以在attr 中查看属性。我确实有hasMore(),但之后一切都为NULL,为什么SCOPE_SUB,因为这是我在函数中更改的主要内容?
  • 我偶尔也会遇到 LDAP 超时,或者只是在没有返回结果时跳过 - 知道吗?
  • 感谢您回到我身边。我的问题中的更新是我正在使用的,显示了我正在使用的搜索,我的功能现在已经略有改变,因为我已经将 LdapConnection 包装在使用中。
  • @PurpleSmurph,您有 AD 用户和计算机吗?
  • 是的,我们使用 AD 登录我们所有的机器 - 如果这就是您的意思吗?我已经用函数原样更新了问题,总是点击LdapException
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-03-18
  • 2016-05-29
  • 1970-01-01
  • 1970-01-01
  • 2014-07-25
  • 1970-01-01
  • 2014-09-20
相关资源
最近更新 更多