通过PHP进行LDAP身份验证-访问组

7gcisfzg  于 2022-12-17  发布在  PHP
关注(0)|答案(2)|浏览(191)

目前我们的网站有一个基本的登录页面(login.php)和一个单独的脚本(auth.php),其中包括通过LDAP对用户进行身份验证的功能。一旦登录,所有用户都有相同的访问级别,我们希望改变这一点。
目前,当用户登录时,我们会获取他们所属的所有组。然后,我们会遍历这些组,以查看他们是否可以通过我们的某个AD组访问系统。如果可以,他们就可以进入站点。
因为我们不希望每个已通过网站身份验证的人都能访问所有内容,所以我们希望更改此设置。我们希望在用户通过身份验证后设置页面级别访问级别。因为用户可能被分配到多个访问组,所以我们希望只为他们提供最低级别的访问权限。
我们将使用session变量来设置访问级别,然后使用类似下面的代码来实现页面级别访问。

if ($_SESSION['access'] != 3)
    {
    // user is logged in but not a ops team member, let's stop him
    die("Access Denied");
    }

下面是当前的auth.php脚本。

登录名.php:

include("auth.php");

验证php

<?php
session_start(); // Initialize session
function authenticate($user, $password)
    {
    $ldap_host = "example.com"; // Active Directory server
    $ldap_dn = "DC=example,DC=com"; // Active Directory DN
    $ldap_manager_group = "Group_1"; // Active Directory manager group
    $ldap_ops_group = "Group_2"; // Active Directory ops group
    $ldap_eng_group = "Group_3"; // Active Directory eng group
    $ldap_eng2_group = "Group_4"; // Active Directory other eng group
    $ldap_usr_dom = "@example.com"; // Domain, for purposes of constructing $user
    $ldap = ldap_connect($ldap_host); // connect to active directory

    if ($bind = @ldap_bind($ldap, $user . $ldap_usr_dom, $password)) // verify user and password
        {
        // valid
        // check presence in groups
        $filter = "(sAMAccountName=" . $user . ")";
        $attr = array(
            "memberof",
            "cn",
            "givenname",
            "sn"
        );
        $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];
        $surname = $entries[0]['sn'][0];
        ldap_unbind($ldap);

        foreach($entries[0]['memberof'] as $grps) // check groups
            {
            if (strpos($grps, $ldap_manager_group)) // is manager, break loop
                {
                $access = 4;
                $group = $ldap_manager_group;
                break;
                }

            if (strpos($grps, $ldap_ops_group)) $access = 3; // is ops team
            $group = $ldap_ops_group;

            if (strpos($grps, $ldap_eng_group)) $access = 2; // is eng team
            $group = $ldap_eng_group;

            if (strpos($grps, $ldap_eng2_group)) $access = 1; // is eng2 team
            $group = $ldap_eng2_group;
            }

        if ($access != 0)
            {
            // establish session variables
            $_SESSION['user'] = $user;
            $_SESSION['access'] = $access;
            $_SESSION['access_group'] = $group;
            $_SESSION['givenname'] = $givenname;
            $_SESSION['sn'] = $surname;
            return true;
            }
          else
            {
            return false; // user has no rights
            }
        }
      else
        {
        return false; // invalid name or password
        }
    }
?>

我们正在考虑为每个访问级别创建新的访问组,如下所示:

  • $access = 1 #访问报告(组=研究中心报告)
  • $access = 2 #访问报告+内容3(组= site_ops)
  • $access = 3 #访问报告+内容1(组=站点内容1)
  • $access = 4 #访问报告+内容2(组=站点内容2)
  • $access = 9号管理员(组=站点管理员)

但是对于如何搜索所有访问组的所有LDAP成员资格并分配最低访问值感到困惑。
我们认为类似这样的东西可以工作,但它与LDAP中数组的输出不匹配。

$grps = array(
    $entries[0]['memberof']
);

if (in_array('site_reporting', $grps))
    {
    $access = 1;
    }
elseif (in_array('site_ops', $grps))
    {
    $access = 2;
    }
elseif (in_array('site_content1', $grps))
    {
    $access = 3;
    }
elseif (in_array('site_content2', $grps))
    {
    $access = 4;
    }
elseif (in_array('site_admin', $grps))
    {
    $access = 9;
    }

任何帮助都将不胜感激!谢谢!

yruzcnhs

yruzcnhs1#

我认为它不匹配的原因是因为您试图仅匹配AD组名称,但您的查询将返回AD架构(CN、OU、DC等)。
一个建议是使用foreach循环和explode来只将组名和结果拆分到一个新数组中,然后将该数组用作if\else语句中的干草堆。

e5nszbig

e5nszbig2#

如果你把access设为位掩码,那么你就去掉了层次概念,人们可以是多个组的成员,每个组不需要是前一个组的超集。
首先为组分配位值:

<?php
const ldap_manager_group = 0b0001; // 1
const ldap_ops_group = 0b0010;     // 2
const ldap_eng_group = 0b0100;     // 4
const ldap_eng2_group = 0b1000;    // 8

然后在测试时将位掩码添加到$access:

$access = 0;
    if (strpos($grps, $ldap_ops_group)){
       access = $access + ldap_ops_group; // is ops team
       $group = $ldap_ops_group;
    }
    if (strpos($grps, $ldap_eng_group)){
       $access = $access + ldap_eng_group; // is eng team
       $group = $ldap_eng_group;
    }
    if (strpos($grps, $ldap_eng2_group)){
       $access = $access + ldap_eng2_group; // is eng2 team
       $group = $ldap_eng2_group;
    }

然后在每一页上测试:

if ($access & ldap_ops_group) {
   echo "You are a member of the ops group<br>\n";
}

相关问题