LDAP - 寻找在PHP / Mysql

时间:2017-08-31 12:51:45

标签: php active-directory ldap

这些是我的先决条件:

  • 用户通过Active Directory进行管理
  • 在LDAP中,它们被分配给确定这些用户权限的组
  • 通过NTLM登录

现在我在显示某些数据之前检查并查看某个用户是否是某个组的成员:

if(is_allowed(USER, '(memberof=CN=Repairgroup,OU=Laboratory,OU=Organization,OU=MyBusiness,DC=somedc,DC=local)')):  
    display some data
endif;

function is_allowed($check, $filter) {
    // connect to ldap
    $ldapconn = ldap_connect(LDAP_HOST) or die("Could not connect to LDAP server.");
    // binding to ldap server
    ldap_bind($ldapconn, LDAP_USER, LDAP_PASS) or die("Error trying to bind: " . ldap_error($ldapconn));

    // search for $filter
    $result = ldap_search($ldapconn, LDAP_TREE, $filter) or die("Error in search query: " . ldap_error($ldapconn));
    $data = ldap_get_entries($ldapconn, $result);

    // check if user is part of LDAP_TREE
    if (!in_multiarray($check, $data)):
        // all done? clean up!
        ldap_close($ldapconn);
        return false;
    endif;
    // all done? clean up!
    ldap_close($ldapconn);
    return true;
}

function in_multiarray($elem, $array) {
    while (current($array) !== false):
        if (current($array) == $elem):
            return true;
        elseif(is_array(current($array))):
            if(in_multiarray($elem, current($array))):
                return true;
            endif;
        endif;
        next($array);
    endwhile;
    return false;
}

现在,如果我想将一个用户分配给故障单,例如我运行以下命令:

// connect to ldap
$ldapconn = ldap_connect(LDAP_HOST);
// binding to ldap server
ldap_bind($ldapconn, LDAP_USER, LDAP_PASS);

// search for $filter
$result = ldap_search($ldapconn, LDAP_TREE, LABORATORY);
$data = ldap_get_entries($ldapconn, $result);
utf8_encoder($data);
for ($i=0; $i<$data["count"]; $i++):
    echo "<tr><td><label class=\"label\"><input type=\"checkbox\" name=\"user[]\" value=\"".$data[$i]["cn"][0]."\" />".$data[$i]["cn"][0]."</label></td></tr>";
endfor;
ldap_close($ldapconn);

进入数据库我只是把名字。如果我分配了更多用户,我会将其分配给&#39;,&#39;那样:

$users = NULL;
        foreach($c_post['user'] as $value):
            $users = $users.$value.", ";
        endforeach;

结果将类似于我的数据库:Alex Foo, Peter Bar

从数据库中读取我只是使用一个简单的爆炸来分离它们。

$iduser = explode(", ", $row->iduser);

也是为了让当前用户浏览我使用这个过滤器:

// User based on Windows-Login (Look up user currently browsing)
define('LDAP_SELF', '(sAMAccountName='.substr($c_server['REMOTE_USER'], 11).')');

现在设置这样就可以很容易地添加用户,管理他们的权利等等。一旦掌握了这些过滤器LDAP的使用,即使部门主管等之间的目标也相当容易。

但对我而言,在我的代码中使用会变得很痛苦。现在我想发送消息并根据用户获取一些统计信息,每次最终都会绑定到LDAP并查找用户。这是我第一次使用LDAP / Active Directory,在此之前我只是在MySQL中使用了充满用户及其ID的表。根据我的代码中的ID,它现在似乎更容易存储,管理和执行操作。

  • 我的代码或使用LDAP的方式有什么可以改进的吗?
  • 我正在使用LDAP&#34;正确&#34;? (我知道答案将基于意见,但只要我不在我的代码中滥用LDAP,我就可以了。)/ / li>
  • 与我的数据库中只有用户相比,每次绑定到LDAP的保存方式是多少?
  • 如果用LDAP做不安全的话我应该每天运行一次脚本和用户一起填充表吗?
  • 更简单的方法来执行下面的操作?

举个例子

我想编辑分配给故障单的用户。首先,我从表中选择值,然后将其展开并列出用户。现在我需要在更新数据库之前将它们组合并检查,如果这些用户仍然是Active Directory的一部分并且具有足够的权限。

  1. 从数据库中选择
  2. 爆炸并显示
  3. 绑定到LDAP以显示所有其他用户
  4. 检查用户是否仍然存在且具有LDAP权限
  5. 合并用户
  6. 更新数据库
  7. 非常感谢您的时间:)

    我最终得到了什么:

    为了让事情变得简单,我有这个:

    if(!isset($_SESSION["DN"]) && !isset($_SESSION["username"])):
        // connect to ldap
        $ldapconn = ldap_connect(LDAP_HOST) or die("Could not connect to LDAP server.");
        // binding to ldap server
        ldap_bind($ldapconn, LDAP_USER, LDAP_PASS) or die("Error trying to bind: " . ldap_error($ldapconn));
    
        // search for $filter
        $result = ldap_search($ldapconn, LDAP_TREE, '(sAMAccountName='.USER.')') or die("Error in search query: " . ldap_error($ldapconn));
        $data = ldap_get_entries($ldapconn, $result);
        utf8_encoder($data);
        ldap_close($ldapconn);
        $_SESSION["DN"] = $data[0]["dn"];
        preg_match('/^CN=(.+?),(?:CN|OU)=.+/', $_SESSION['DN'], $matches);
        $_SESSION["username"] = $matches[1];
    endif;
    

    如果我需要显示用户,我有这个:

    // connect to ldap
    $ldapconn = ldap_connect(LDAP_HOST) or die("Could not connect to LDAP server.");
    // binding to ldap server
    ldap_bind($ldapconn, LDAP_USER, LDAP_PASS) or die("Error trying to bind: " . ldap_error($ldapconn));
    
    ?>    
    <div id="container">
      <form action="#" method="post">
        <table>
          <tbody>
            <?php
    
    echo "<tr><td>Repairgroup</td></tr>";
    
    $result = ldap_read($ldapconn,
        "CN=Repairgroup,OU=Laboratory,OU=Organization,OU=MyBusiness,DC=domain,DC=local",
        "(objectClass=*)",
        ["member"]
    );
    $data = ldap_get_entries($ldapconn, $result);
    utf8_encoder($data);
    
    foreach($data[0]["member"] as $k => $v):
        if(!is_int($v)):
            preg_match('/^CN=(.+?),(?:CN|OU)=.+/', $v, $name);
            echo "<tr><td><label class=\"label\"><input type=\"checkbox\" name=\"user[]\" value=\"".$v."\" />".$name[1]."</label></td></tr>\n";
        endif;
    endforeach;
    ?>
       </tbody>
     </table>
    </form>
    

    然后我会将一个或多个DN存储在我的数据库中,并与|分开,之后我只需要显示我使用的名称:

    preg_match_all('/\bCN=\b(.+?),/', $row->iduser, $name, PREG_SET_ORDER, 0);
    echo "<td class=\"worker\"><span>";
    for($i = 0; $i < count($name); $i++):
      echo "<p>".$name[$i][1]."</p>\n";
    endfor;
    echo "</span></td>\n";
    

    这是我的正则表达式的示例:https://regex101.com/r/s6PbOR/1/

    并检查某人是否有权访问:

    if(is_allowed($_SESSION["DN"], 'CN=Repairgroup,OU=Laboratory,OU=Organization,OU=MyBusiness,DC=somedc,DC=local')):  
        display some data
    endif;
    

    感谢Esteban指导我这个! :)非常感谢

1 个答案:

答案 0 :(得分:1)

  
      
  • 我的代码或使用LDAP的方式有什么可以改进的吗?
  •   
  • 我正在使用LDAP&#34;正确&#34;? (我知道答案将基于意见,但只要我不在我的代码中滥用LDAP,我就可以了。)/ / li>   

您将LDAP目录用作RDBM后端。您应该尝试按预期使用它:分层数据库。

在你的代码中:

  1. 请求为组
  2. 设置属性USER的每个用户
  3. 检查DN是否属于此群组
  4. 但是:您拥有组member,LDAP具有委托用户成为组的一部分的机制应该存在于目录中。

    所以:我要做的是:

    检索组的$result = ldap_read($ldapconn, "CN=Repairgroup,OU=Laboratory,OU=Organization,OU=MyBusiness,DC=somedc,DC=local", "(objectClass=*)", ["member"] ) 属性:

    ldap_read

    这样可以节省您搜索目录的负担,因为您可以直接访问提供读取它的唯一ID的条目(DN)

      
        
    • 与我的数据库中只有用户相比,每次绑定到LDAP的保存方式是多少?
    •   
    • 如果用LDAP做不安全的话我应该每天运行一次脚本和用户一起填充表吗?
    •   

    LDAP是一种协议,用于处理比写入更高的读取/搜索比率,因此只要优化了请求/搜索,每次需要时都应该没有问题来寻找用户。

      
        
    • 更简单的方法来执行下面的操作?
    •   
    • 我会存储用户的DN,而不是在票证表中存储一些用户的显示名称。它有2个好处
      • 允许您member用户输入,而无需事先执行搜索以查找此信息
      • 您将从数据库中获取的爆炸数组可以直接与LDAP组上ldap_read返回的member属性数组进行比较(如前所述)
    • 检查用户是否仍然存在:
      • 将出现在组的ldap_read属性中的用户应该存在于目录中,因此您需要检查的列表只是数据库中存在的列表而不是组中的
      • 如果不再将它们分配给故障单,因为它们不在组中,则不再检查状态,否则您只需要32 no such object用户输入而不检索任何属性,如果用户不存在您将遇到LDAP错误:// USER would be the DN in this case if(is_allowed(USER, 'CN=Repairgroup,OU=Laboratory,OU=Organization,OU=MyBusiness,DC=somedc,DC=local')): display some data endif; function is_allowed($check, $dn) { // connect to ldap $ldapconn = ldap_connect(LDAP_HOST) or die("Could not connect to LDAP server."); // binding to ldap server ldap_bind($ldapconn, LDAP_USER, LDAP_PASS) or die("Error trying to bind: " . ldap_error($ldapconn)); // search for $dn $result = ldap_read($ldapconn, $dn, "(objectClass=*)", ["member"] ) or die("Error in search query: " . ldap_error($ldapconn)); $data = ldap_get_entries($ldapconn, $result); ldap_close($ldapconn); return in_array($check, $data[0]['member']); }

    它比进行多次搜索更快更有效率

    如果您这样做,要检查用户是否在组中并且被允许,您发布的代码将仅为:

     var new_form = $('.form-model').children().first().clone(true);
    

    (注意:您需要稍微调整一下以处理从LDAP目录中删除的用户返回的错误代码)