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的一部分并且拥有足够的权限,那么现在我需要将它们结合起来并在更新数据库之前进行检查。
- SELECT从数据库
- 爆炸,显示
- 绑定到LDAP显示所有其他用户
- 检查,如果用户仍然存在并有LDAP权利
- 结合用户
- 更新数据库
谢谢你这么多你的时间:)
我最终什么了:
为了方便起见我有这样的:
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。您应该尝试按预期使用它:分层数据库。
在你的代码:
- 请求具有属性
memberof
集为一组 - 检查是否
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目录中删除的错误代码返回)
首先感谢你的回答!我正在研究它,这非常有帮助。然而,我有两个关于你的解决方案的问题:** 1。**你如何将DN输入数据库? *我的想法是存储DN并将其分隔为“|'”。要显示名称,它应该足以提取CN = Name Lastname并显示它,而不是再次执行ldap_read。* ** 2。**当您说错误代码返回时,请您谈谈Error 32 no such object'? – floGalen
我正在阅读[分层数据库模型](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
@floGalen要存储DN,取决于你要使用什么样的语言,因为DN中没有无效字符(有些需要转义),所以如果系统上的更多指南不使用你的DN中的分隔符,而不是所有LDAP DN通用的绝对规则。对于你的第二点,是的,我谈到了“错误32”。这只是从内存中,所以我不知道如果一个非现有的DN上的'ldap_read'会返回一个错误或一个空的结果,所以万一它是错误,你必须处理它,而不是做一个'死'剧本。 – Esteban