1

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

在这个程序的某个时刻,我需要将某些用户标记为“经理”,最简单的方法是如果他们是某个经理组的成员,则存储一个标志 VIA 会话变量,如上所述问题我遇到的是用户没有出现在他们的某些组中,所以这不起作用,可以访问经理的组没有出现在我的 MemberOf 区域中。在最后阶段,我将必须经过 5-6 组并将所有成员添加到数据库中,这是一个类似的问题,应该有类似的解决方案,所以如果我想出一个石头,也许我可以用 1 块石头杀死两只鸟也。我所说的这个问题的意思是我需要抓住一个组,比如“用户 HR”

代码:

<?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() 而没有其他内容。任何想法?它们包含其他安全组。这就是我们想要的工作,我们希望能够找到这些组的成员,如果我将 $ldap_dn 设置为“CN=Company,DC=Company,DC=Local”,我附加的第二个代码有时会起作用它将打印用户 OU 中的所有用户,然后进入那里的所有 OU 并打印这些 OU 中的用户,但我们实际需要的 OU 是具有 in out board 组的 OU。如果我将该路径指定为 $ldap_dn,它只会打印 array() 而没有其他内容。任何想法?它们包含其他安全组。这就是我们想要的工作,我们希望能够找到这些组的成员,如果我将 $ldap_dn 设置为“CN=Company,DC=Company,DC=Local”,我附加的第二个代码有时会起作用它将打印用户 OU 中的所有用户,然后进入那里的所有 OU 并打印这些 OU 中的用户,但我们实际需要的 OU 是具有 in out board 组的 OU。如果我将该路径指定为 $ldap_dn,它只会打印 array() 而没有其他内容。任何想法?在那里并打印来自那些 OU 的用户,但我们实际需要的 OU 是具有 in out board 组的 OU。如果我将该路径指定为 $ldap_dn,它只会打印 array() 而没有其他内容。任何想法?在那里并打印来自那些 OU 的用户,但我们实际需要的 OU 是具有 in out board 组的 OU。如果我将该路径指定为 $ldap_dn,它只会打印 array() 而没有其他内容。任何想法?

4

1 回答 1

0

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

于 2016-04-28T17:45:46.517 回答