LDAP - 寻找一种更好的方式在PHP来管理用户/ MySQL的

问题描述:

这些都是我的先决条件:LDAP - 寻找一种更好的方式在PHP来管理用户/ MySQL的

  • 用户是通过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); 

和数据库中我只是把名字。如果我赋予它更多的用户我单独他们“”这样的:

$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? (我知道答案将基于意见,但只要我不滥用LDAP与我的代码我很好,我猜)
  • 如何保存每次绑定到LDAP相比,只是有我的数据库中的用户?
  • 如果不安全使用LDAP,我应该每天运行一次某些脚本向用户填充表格?
  • 更简单的方式来执行下面的东西?

作为一个例子

我想编辑分配给票的用户。首先,我从我的表中选择值,然后将其分解并列出用户。现在,如果这些用户仍然是Active Directory的一部分并且拥有足够的权限,那么现在我需要将它们结合起来并在更新数据库之前进行检查。

  1. SELECT从数据库
  2. 爆炸,显示
  3. 绑定到LDAP显示所有其他用户
  4. 检查,如果用户仍然存在并有LDAP权利
  5. 结合用户
  6. 更新数据库

谢谢你这么多你的时间:)


我最终什么了:

为了方便起见我有这样的:

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,与|分开d后,当我不得不只显示我用这个名字:

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引导我走向这个! :)非常感谢

  • ,请问有什么我可以在我的代码或使用LDAP的方式提高?
  • 我是否正确地使用LDAP? (我知道答案将根据意见,但只要我不跟我的代码滥用LDAP我与它的罚款我猜)

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

在你的代码:

  1. 请求具有属性memberof集为一组
  2. 检查是否USER是该组

的一部分,但每个用户:你有组DN,LDAP具有委托用户成为组的一部分的机制,该组应该存在于该目录中。

SO:我可能做的就是:

检索member属性组:

$result = ldap_read($ldapconn, 
"CN=Repairgroup,OU=Laboratory,OU=Organization,OU=MyBusiness,DC=somedc,DC=local", 
"(objectClass=*)", 
["member"] 
) 

这样可以节省你搜索到该目录中的负载,因为你直接访问该条目提供唯一的ID读(DN)

  • 如何保存会是绑定到每次LDAP相比,只是有我的数据库中的用户?
  • 如果不安全使用LDAP,我应该每天运行一次某些脚本向用户填充表格?

LDAP是被用来处理一个比多读的更高的协议/搜索比写,所以只要请求/搜索被优化,应该没有问题寻找一个用户每你需要它的时候。

  • 更简单的方法,像下面执行的东西吗?
  • 而是在售票台存储用户的一些显示名称的我会存储用户的DN。它有2个好处
    • 允许你ldap_read用户条目,而无需进行搜索,找到此信息事先
    • 的爆炸,你会从你的数据库获得阵列照片直接进行比较与member属性返回数组由ldap_read上的LDAP基(如前所示)
  • 检查是否用户仍然呈现:
    • 这将是存在于在使用者该组的属性应该存在于该目录中,因此您需要检查的列表仅为数据库中存在的列表,并且不在组中
    • 如果不应将它们分配给票据,因为它们不在组,那么就没有再检查存在,否则你只需要ldap_read用户进入而不检索任何属性,如果用户不存在,你将有一个LDAP错误:32 no such object

它将比进行多次搜索要快得多,效率更高

如果你做这种方式,来检查,如果用户存在一个组中,并且被允许,你发布的代码只会是:

// 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']); 
} 

(注意:您将需要调整这个有点处理由用户从LDAP目录中删除的错误代码返回)

+0

首先感谢你的回答!我正在研究它,这非常有帮助。然而,我有两个关于你的解决方案的问题:** 1。**你如何将DN输入数据库? *我的想法是存储DN并将其分隔为“|'”。要显示名称,它应该足以提取CN = Name Lastname并显示它,而不是再次执行ldap_read。* ** 2。**当您说错误代码返回时,请您谈谈Error 32 no such object'? – floGalen

+0

我正在阅读[分层数据库模型](https://en.wikipedia.org/wiki/Hierarchical_database_model)和[关系数据库管理系统](https://en.wikipedia.org/wiki/Relational_database_management_system)在你的答案中给出的关键字找到了用ldap查看php中用户管理的详细信息。 https://stackoverflow.com/a/28787550/8188398或https://www.null-byte.org/development/php-active-directory-ldap-authentication/以及http://www.tldp.org/ HOWTO/LDAP-HOWTO /这极大地改进了我对LDAP的使用以及我对事物工作方式的理解。再次感谢! – floGalen

+0

@floGalen要存储DN,取决于你要使用什么样的语言,因为DN中没有无效字符(有些需要转义),所以如果系统上的更多指南不使用你的DN中的分隔符,而不是所有LDAP DN通用的绝对规则。对于你的第二点,是的,我谈到了“错误32”。这只是从内存中,所以我不知道如果一个非现有的DN上的'ldap_read'会返回一个错误或一个空的结果,所以万一它是错误,你必须处理它,而不是做一个'死'剧本。 – Esteban