如何根据 IIS windows 身份验证过滤 ldap 活动目录用户信息并在 php 网站中显示该信息?

how to filter ldap active directory users information based on IIS windows authentication and display that information in php website?

我正在创建一个 Intranet PHP 网站,没有任何登录要求。我有一个 IIS 应用程序(基于 PHP),身份验证是使用 Windows 身份验证完成的(禁用匿名身份验证)。我已经通过一些 GPO 调整成功地设置了 IIS 和 windows 身份验证。我的简单 PHP 页面包含 $_SERVER['REMOTE_USER'];,因此没有任何登录提示的活动目录用户可以看到 DOMAIN\User.Name

在我的理解中IIS Windows认证非常有限,只能显示用户名和域名。因此,我启用了 LDAP 以显示有关用户的更多信息,例如显示名称或 phone 号码。但我被困在这里是因为据我所知,LDAP 使用用户名和密码绑定来检索信息。当我使用活动目录管理员凭据时,它会为我提供所有用户信息的 table,但如何过滤 table 以仅显示当前用户信息(基于 windows 身份验证)。

代码:

<?php
$current_user = get_current_user();
$ldap_password = 'AdminPassword';
$ldap_username = 'Administrator@domain.name';
$ldap_connection = ldap_connect("domain.name");

if (FALSE === $ldap_connection){
    echo 'ERROR';
}

ldap_set_option($ldap_connection, LDAP_OPT_PROTOCOL_VERSION, 3) or die('Unable to set LDAP protocol version');
ldap_set_option($ldap_connection, LDAP_OPT_REFERRALS, 0); 

if (TRUE === ldap_bind($ldap_connection, $ldap_username, $ldap_password)){

    $ldap_base_dn = 'OU=Users,DC=domain,DC=name';

    $search_filter = '(|(objectCategory=person)(objectCategory=contact))';

    $result = ldap_search($ldap_connection, $ldap_base_dn, $search_filter);

    if (FALSE !== $result){
        $entries = ldap_get_entries($ldap_connection, $result);

        echo '<h2>Result</h2></br>';
        echo '<table border = "1"><tr><td>Username</td><td>Last Name</td><td>First Name</td></tr>';

        for ($x=0; $x<$entries['count']; $x++){

            $LDAP_samaccountname = "";

            if (!empty($entries[$x]['samaccountname'][0])) {
                $LDAP_samaccountname = $entries[$x]['samaccountname'][0];
                if ($LDAP_samaccountname == "NULL"){
                    $LDAP_samaccountname= "";
                }
            } else {

                $LDAP_uSNCreated = $entries[$x]['usncreated'][0];
                $LDAP_samaccountname= "CONTACT_" . $LDAP_uSNCreated;
            }

            //Last Name
            $LDAP_LastName = "";

            if (!empty($entries[$x]['sn'][0])) {
                $LDAP_LastName = $entries[$x]['sn'][0];
                if ($LDAP_LastName == "NULL"){
                    $LDAP_LastName = "";
                }
            }

            //First Name
            $LDAP_FirstName = "";

            if (!empty($entries[$x]['givenname'][0])) {
                $LDAP_FirstName = $entries[$x]['givenname'][0];
                if ($LDAP_FirstName == "NULL"){
                    $LDAP_FirstName = "";
                }
            }

            echo "<tr><td><strong>" . $LDAP_samaccountname ."</strong></td><td>" .$LDAP_LastName."</td><td>".$LDAP_FirstName."</td></tr>";


        }
    }

    ldap_unbind($ldap_connection);
    echo("</table>");
}
?>

编辑:管理通过编辑 LDAP 过滤器来过滤当前用户:

$search_filter = "(|(objectCategory=persons)(sAMAccountName=*$current_user*))";

您的查询几乎正确,但它以迂回的方式工作:)

没有 objectCategory 叫作 persons。只是 person(没有 "s")。因此 objectCategory=persons 对于您域中的每个对象始终为 false。但它有效,因为您使用的是 OR (|).

所以它真正使用的唯一标准是 sAMAccountName=*$current_user*。但这要求 sAMAccountName 包含 $current_user 的任何对象。这会产生两个意想不到的后果:

  1. 如果您有一个名为 neil 的用户和另一个名为 oneil 的用户,那么每当 neil 登录时,您都会在该搜索中找到这两个帐户。
  2. 因为您的搜索条件以通配符 (*) 开头,所以无法使用索引来查找帐户。这意味着它必须查看您域中的每个对象才能找到匹配项。如果您的域较小,这可能无关紧要,但域中的对象越多,所需时间就越长。

IIS 为您提供了准确的用户名,因此无需进行 "contains" 比较。所以你的查询可以简化为:

(sAMAccountName=$current_user)

由于 sAMAccountName 是一个索引属性,这将是一个超级快速的查询。

您经常会看到将搜索限制为用户帐户的附加条件,例如(注意 &):

(&(objectClass=user)(objectCategory=person)(sAMAccountName=$current_user))

但实际上,只有用户才能向 IIS 进行身份验证,并且 sAMAccountName 在所有对象类型中都是唯一的,因此 真的 无关紧要。