【问题标题】:LDAP Finding Members of a group PHPLDAP 查找组 PHP 的成员
【发布时间】:2016-04-28 16:33:24
【问题描述】:

我有一个关于 Active Directory 中组的用户成员资格以及使用 PHP 获取此类成员资格的问题。我的大问题/情况是我正在制作一个网站,基本上我正在尝试根据 Active Directory 中的组分配管理员,我知道如何检查帐户状态的成员,但我的问题是有一些组没有显示在那里,并且没有显示的组之一是我需要的组。有没有办法可以检查谁是该组的成员,而不是检查该用户是否是该组的成员。或者,如果有人知道为什么某些组没有出现在我的搜索中,我更愿意以这种方式搜索成员资格,因为这样检查用户是否在该组中将是一个简单的逻辑语句,我的代码在下面并且它确实有效,但作为我说有些组没有出现,我想我在某处读到了有关如何存储成员资格的信息,以及它是直接成员资格,还是您是另一个组成员的组的成员。我们用作默认组的一个组是域用户,但没有人在 memberOf 数组中拥有该组,即使该组的成员资格是直接的,因为该组的成员都是用户而不是包含用户的其他安全组。

在这个程序的某个时刻,我需要将某些用户标记为“经理”,最简单的方法是如果他们是某个经理组的成员,则存储一个标志 VIA 会话变量,如前所述上面我遇到的问题是用户没有出现在他们的某些组中,所以这不起作用,可以访问经理的组没有出现在我的 MemberOf 区域中。在最后阶段,我将必须经过 5-6 组并将所有成员添加到数据库中,这是一个类似的问题,应该有类似的解决方案,所以如果我想出一个石头,也许我可以用 1 块石头杀死两只鸟也。我的意思是这个问题是我需要获取一个组,例如“用户 HR”,然后通过给定名称和姓氏以及其他字段的一些默认值将它们全部上传到数据库,但我不知道如何从组中抓取用户,我知道如何抓取用户的组,但即使这样也不能抓取 100% 的组,如果我可以颠倒该顺序并充当组并检查我自己的成员,这将使事情变得非常容易,我们目前用来为我们做这一切的应用程序是在 ASP.net 中,但是已经有 10 年左右的历史了,并且有一个硬编码到访问组等的管理员帐户,即使这样做我仍然不确定我是如何做到的会得到一个组的成员。

代码:

<?php
$ldap = ldap_connect("192.168.1.**");
$ldap_dn = "DC=************,DC=local";
ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
ldap_set_option( $ldap, LDAP_OPT_PROTOCOL_VERSION, 3 );
$access = NULL;
if ($bind = ldap_bind($ldap, "***********\\" . $_POST['username'], $_POST['password'])) {
    $filter = "(sAMAccountName=" . $_POST['username'] . ")";
    $attr = array("memberof","givenname","sn","mail");
    $result = ldap_search($ldap, $ldap_dn, $filter, $attr) or exit("Unable to search LDAP server");
    $entries = ldap_get_entries($ldap, $result);
    $givenname = $entries[0]['givenname'][0] . " " . $entries[0]['sn'][0];
    ldap_unbind($ldap);
    //var_dump($entries[0]["sn"][0]);
    //var_dump($givenname);
    //var_dump($entries[0]);
    // check groups
    foreach($entries[0]['memberof'] as $grps) {
        // is manager, break loop
        //if (strpos($grps, $ldap_manager_group)) { $access = 2; break; }
        // is user
        //var_dump($grps);
        if (strpos($grps, "****** * *** *****")) $access = "****** *";
        if (strpos($grps, "*** Group")) $access = "***";
        if (strpos($grps, "*** Group")) $access = "***";
        if (strpos($grps, "***")) $access = "***";
        if (strpos($grps, "*** Group")) $access = "***";
        if (strpos($grps, "***")) $access = "***";
    }
    if ($access != NULL) {
        // establish session variables
        $_SESSION['user'] = $_POST['username'];
        $_SESSION['access'] = $access;
        $_SESSION['givenname'] = $givenname;
        $_SESSION['email'] = $entries[0]['mail'][0];
        return true;
        } else {
        //echo "No rights?";
        // user has no rights
        return false;
    }
} else {
  //header("Location: login.php?Error=Invalid Identity");
    echo "Elese Here";
}
?>

编辑:

我一直在尝试使用本教程:samjlevy.com,我大部分都理解它,但我遇到了一些错误:

Warning: ldap_search(): Search: Operations error in C:\inetpub\wwwroot\InOutBoard\test.php on line 62

Warning: ldap_get_entries() expects parameter 2 to be resource, boolean given in C:\inetpub\wwwroot\InOutBoard\test.php on line 63

Warning: array_shift() expects parameter 1 to be array, null given in C:\inetpub\wwwroot\InOutBoard\test.php on line 66

Warning: Invalid argument supplied for foreach() in C:\inetpub\wwwroot\InOutBoard\test.php on line 72
Array ( )

它们似乎都与搜索有关,因为它不工作它返回一个 NULL 集到结果,这将不允许其他部分运行。我不确定我的 $ldap_dn 是否正确,因为我使用的是上面 php 代码中的同一个。我的布局如下(我是新手,我相信这是正确的):DC=company,DC=local,所以它应该是我想要的组:CN=Grouplooking For,OU=lowestLevel Ou,OU=Groups ,OU=公司,DC=公司,DC=本地

我必须将它用作我的 $ldap_dn 吗?

编辑 2:(更新代码)

此代码显示用户所在的所有组并且运行良好,有没有办法编写第二个页面,使用类似的页面来获取其中一个组并从中获取所有成员?

<?php

$ldap = ldap_connect("192.168.1.**");
$ldap_dn = "DC=Company,DC=local";
ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
ldap_set_option( $ldap, LDAP_OPT_PROTOCOL_VERSION, 3 );
$access = NULL;
if ($bind = ldap_bind($ldap, "**********\\" . $_POST['username'], $_POST['password'])) {
    $filter = "(sAMAccountName=" . $_POST['username'] . ")";
    $attr = array("memberof","givenname","sn","mail","distinguishedname");
    $result = ldap_search($ldap, $ldap_dn, $filter, $attr) or exit("Unable to search LDAP server");
    $entries = ldap_get_entries($ldap, $result);
    $givenname = $entries[0]['givenname'][0] . " " . $entries[0]['sn'][0];
    //ldap_unbind($ldap);
    //var_dump($entries[0]["sn"][0]);
    //var_dump($givenname);
    //var_dump($entries[0]);
    var_dump($entries[0]['distinguishedname'][0]);

    $gFilter = "(&(objectClass=group)(member:1.2.840.113556.1.4.1941:=".$entries[0]['distinguishedname'][0]."))";
    $gAttr = array("cn");
    $result1 = ldap_search($ldap, $ldap_dn, $gFilter, $gAttr) or exit("Unable to search LDAP server");
    $groups = ldap_get_entries($ldap, $result1);
    var_dump($groups);
    // check groups
    foreach($entries[0]['memberof'] as $grps) {
        // is manager, break loop
        //if (strpos($grps, $ldap_manager_group)) { $access = 2; break; }

        // is user
        //var_dump($grps);
        if (strpos($grps, "****** * *** *****")) $access = "****** *";
        if (strpos($grps, "*** Group")) $access = "***";
        if (strpos($grps, "*** Group")) $access = "***";
        if (strpos($grps, "***")) $access = "***";
        if (strpos($grps, "*** Group")) $access = "***";
        if (strpos($grps, "***")) $access = "***";

    }

    if ($access != NULL) {
        // establish session variables
        $_SESSION['user'] = $_POST['username'];
        $_SESSION['access'] = $access;
        $_SESSION['givenname'] = $givenname;
        $_SESSION['email'] = $entries[0]['mail'][0];
        return true;
        } else {
        //echo "No rights?";
        // user has no rights
        return false;
    }
} else {
  //header("Location: login.php?Error=Invalid Identity");
    echo "Elese Here";
}
?>

第二页:这个页面应该找到一个组的成员,看起来它可能正在尝试这样做,但没有选择组的成员,而是我们的 OU 之一。查看下面的代码,了解布局及其抓取的内容。

<?php
function get_members($group=FALSE,$inclusive=FALSE) {
    $ldap_host = "192.168.1.***";
    $ldap_dn = "OU=******,OU=*****,OU=**********,DC=Company,DC=local";
    $ldap_usr_dom = "@".$ldap_host;
    $user = "*******";
    $password = "******";
    $keep = array(
        "samaccountname",
        "distinguishedname"
    );
    $ldap = ldap_connect($ldap_host) or die("Could not connect to LDAP");
   ldap_bind($ldap, "REGION5SYSTEMS\\" . $user, $password) or die("Could not bind to LDAP");ry
    if($group) $query = "(&"; else $query = ""; 
    $query .= "(&(objectClass=user)(objectCategory=person))";
    if(is_array($group)) {
        // Looking for a members amongst multiple groups
            if($inclusive) {
                $query .= "(|";
            } else {
                $query .= "(&";
            }
            foreach($group as $g) $query .= "(memberOf=CN=$g,$ldap_dn)";
            $query .= ")";
    } elseif($group) {
        $query .= "(memberOf=CN=$group,$ldap_dn)";
    }
    if($group) $query .= ")"; else $query .= "";
    $results = ldap_search($ldap,$ldap_dn,$query);
    $entries = ldap_get_entries($ldap, $results);
    array_shift($entries);
    $output = array(); // Declare the output array
    $i = 0; // Counter
    // Build output array
    foreach($entries as $u) {
        foreach($keep as $x) {
            // Check for attribute
            if(isset($u[$x][0])) $attrval = $u[$x][0]; else $attrval = NULL;
            $output[$i][$x] = $attrval;
        }
        $i++;
    }

    return $output;
}

// Example Output
print_r(get_members()); // Gets all users in 'Users'
print_r(get_members("Group I'm search for")); // Gets all members of 'Test Group'
?>

所以我们的 DC 是 DC=CompanyName,DC=Local,然后我们有文件夹和 OU,其中一个 OU 被命名为“CompanyName”,并且嵌套在其中的是 OU,例如管理员计算机、联系人、组等。 . 我正在查看的 OU 是用户并嵌套在我们建筑物中的不同组织(他们使用我们的域)和一个为此项目制作的额外 OU。该项目的背景是一名员工 inoutBoard,因此我们在该 OU 中有 3 个安全组,一个用于其他组织的成员,一个用于我们组织的成员,一个用于我们组织及其组织的经理,基本上是可以改变的人如果他们忘记这样做,其他人的状态。我们理想情况下想要做的是有某种同步按钮,可以检查这些组的成员,然后将它们上传到数据库以及一些默认值,例如不在办公室的默认状态和没有描述或类似的东西.这些组也不包含人员,它们包含其他安全组。这就是我们想要的工作,我们希望能够找到这些组的成员,如果我将 $ldap_dn 设置为“CN=Company,DC=Company,DC=Local”,我附加的第二个代码有时会起作用它将打印用户 OU 中的所有用户,然后进入那里的所有 OU 并打印这些 OU 中的用户,但我们实际需要的 OU 是具有 in out board 组的 OU。如果我将该路径指定为 $ldap_dn,它只会打印 array() 而没有其他内容。有什么想法吗?

【问题讨论】:

    标签: php active-directory ldap memberof


    【解决方案1】:

    memberOf 属性将仅包含直接组成员身份,因此不会列出递归成员身份。但是,您可以像这样专门查询用户的递归组成员身份(以便在绑定后直接调整您的代码):

    $filter = "(sAMAccountName=" . $_POST['username'] . ")";
    $attr = array("givenname","sn","mail", "distinguishedname");
    $result = ldap_search($ldap, $ldap_dn, $filter, $attr) or exit("Unable to search LDAP server");
    $entries = ldap_get_entries($ldap, $result);
    
    $gFilter = "(&(objectClass=group)(member:1.2.840.113556.1.4.1941:=".$entries[0]['distinguishedname'][0]."))";
    $gAttr = array("cn");
    $result = ldap_search($ldap, $ldap_dn, $gFilter, $gAttr) or exit("Unable to search LDAP server");
    $groups = ldap_get_entries($ldap, $result);
    

    目前尚未测试,但这是一般过滤器和执行此操作的过程。获取用户的DN,然后使用匹配规则OID1.2.840.113556.1.4.1941递归获取组。

    您没有显示“域用户”组的原因是因为这是 AD 中的“特殊”主要组,存储在用户的 primaryGroupId 属性中。此处的其他信息:

    https://support.microsoft.com/en-us/kb/297951

    【讨论】:

    • 我正在尝试找出 OID 规则,我是否必须将该数字更改为我自己拉的数字?
    • 另外,代码给出了这个错误:警告:ldap_search(): 4 is not a valid ldap link resource in C:\inetpub\wwwroot\InOutBoard\authorize.php on line 22 这是否必须与 gAttr 区域有关吗?
    • 不,OID 将始终是那个数字。该过滤器中唯一真正改变的是最后出现的内容(当前放置distinguishedName 属性值的位置,因为这将根据用户登录的内容而改变)。至于你的错误......这似乎很奇怪。我已经检查了很多次逻辑,我不确定你是如何理解的。我将首先从您的代码中取出 ldap_unbind 语句,因为这不应该是必需的。您的脚本看起来是否仍与原始帖子中的一样?
    • 我很尴尬我错过了,确实在第二次使用它之前解除绑定 $ldap 会出现错误。我完全错过了在那里看到它,但是确实纠正了错误,并且 $groups 的 var_drump 显示了所有 100% 完美的组以及我需要检查我的会员资格(我的意思是当前登录的人)。不过,我还有一个问题,那就是我可以以某种方式检查特定组中的人员吗?那就是我可以将所有成员上传到数据库而无需他们登录,我的字符不足,所以如果你想知道我为什么需要这样做,我可以解释
    • 尝试这样做,但它一直列出 OU 而不是安全组的成员,有什么帮助吗? samjlevy.com/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-03
    • 1970-01-01
    • 2022-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多