概述
PHP8.0连接LDAP
最近刚对接了下ldap服务,也是踩了一些坑,这里展示一下本地的开发过程以及部分代码
参考文档:
本地docker搭建ldap服务文档参考地址
PHP文档
准备:
- 启动一个开发环境的容器。
docker run -e TZ="Asia/Shanghai" -e LD_PRELOAD="/usr/lib/preloadable_libiconv.so php" --name base_openldap -v D:/WWW:/data -p 9605:9605 -it --privileged -u root --entrypoint /bin/sh hyperf/hyperf:8.0-alpine-v3.15-swoole-v4.8.7
- 检查容器内PHP的ldap扩展是否开启,直接命令行或者phpinfo搜索。
php -module | grep ldap
,php -r "phpinfo();" | grep LDAP
- 如果没有ldap扩展,就安装扩展。用的镜像是alpine linux,alpine linux下apk的安装命令:
apk search php-ldap //寻找合适的版本
,apk add php8-ldap //安装
,容器内默认php扩展目录/usr/lib/php8/modules/
,容器内默认php.ini
配置文件所在位置/etc/php8/
。 - 将修改后的容器重新打包为镜像(这一步看自己),
docker commit -m="增加ldap扩展" -a="szh" 5419967f4cf8 hyperf_ldap //给装好扩展的容器生成一个镜像
,docker tag c236d50c41c5 username/hyperf_ldap:1.0 //给生成好的镜像打一个tag(tag最好前面拼接用户名)
,docker push username/hyperf_ldap:1.0 //试试推送到dockerhub
- 参考ldap服务文档搭建,下载
docker-compose.yml
,修改好自己的配置后,docker-compose up
启动服务 - 容器之间互相访问,需要在一个网络里面,两种加入网络方式:
--net=openldap_default //启动容器时指定网络
,docker network connect openldap_default 容器id //容器运行时,直接指定网络到openldap_default
docker network ls
, 查看刚刚启动的ldap网络。- 运行刚打包好的镜像,并直接加入ldap服务的网络中,
docker run -e TZ="Asia/Shanghai" -e LD_PRELOAD="/usr/lib/preloadable_libiconv.so php" --name demo_openldap -v D:/WWW:/data -p 9705:9705 -it --privileged -u root --entrypoint /bin/sh --net openldap_default user/hyperf_ldap:1.0
errorCode类是网上找了几个ldap_errno错误代码;开发时候多看一下PHP官方文档,一些方法高版本被修改或废弃了
<?php
/*
* @author:
* @name:ldap服务连接
* @desc:
* @LastEditTime:
*/
namespace AppLibPluginsLdap;
use HyperfDiAnnotationInject;
class Ldap
{
public $ldapconn = false;
/**
* @Inject()
* @var LdapCode
*/
protected $errorCode;
/**
* name: ldap资源连接
* Date: 2022/10/12 14:24
* @param $ldapuri
// 例如: ldap://ldap.example.com:389
* @param $username // 例如: cn=admin,dc=example,dc=org
* @param $password // 例如: 123456
*/
public function connect($ldapuri, $username, $password)
{
// 地址连接 注意这里并没有真正连接服务器,只是做了一个参数初始化和检测的操作
$this->ldapconn = @ldap_connect($ldapuri); // 连接ldap
if (FALSE === $this->ldapconn) {
error(200, "ldap_connect 错误");
}
ldap_set_option($this->ldapconn,LDAP_OPT_PROTOCOL_VERSION,3);
ldap_set_option($this->ldapconn, LDAP_OPT_REFERRALS, 0);
// 进行登录用户验证 绑定到具有指定 RDN 和密码的 LDAP 目录 这里才是真正连接服务器
if (TRUE !== ldap_bind($this->ldapconn, $username, $password)) {
error(200, "ldap_bind 错误");
}
}
/**
* name: 添加条目、编辑条目
* Date: 2022/10/12 15:36
* @param $params //参数里面必须包含的验证字段 un_parent_dn(上级所在域)、un_cn(自己的cn)
* @return bool
*/
public function myldap_save($params)
{
$dn = $params['un_cn'].','.$params['un_parent_dn']; //即将添加或修改的节点
unset($params['un_cn'], $params['un_parent_dn']);
//在ldap某个组织中搜索是否已经存在相应数据
$detail = $this->myldap_detail($dn);
$entryInfo = $params;
if($detail == false){
//不存在就添加
$bool = ldap_add($this->ldapconn, $dn, $entryInfo);
}else{
//存在就编辑
//$bool = ldap_modify($this->ldapconn, $dn, $entryInfo);//ldap_modify不能对属性新增、删除
$bool = ldap_mod_replace($this->ldapconn, $dn, $entryInfo);//ldap_mod_replace可以对属性新增、删除
}
return $bool;
}
/**
* name: 判断条目是否存在,存在返回条目信息,不存在返回false
* Date: 2022/10/12 14:30
* @param $dn
* @return array|false
*/
public function myldap_detail($dn)
{
$filter = "(".explode(',', $dn)[0].")";
//搜索ldap中是否已经存在相应数据
$sr = @ldap_read($this->ldapconn, $dn, $filter);
if(!$sr){
error(200, $this->errorCode->codeMsg($this->ldapconn));
}
$entry = ldap_get_entries($this->ldapconn, $sr);
return empty($entry['count'])? false: $entry;
}
/**
* name: 删除条目
* Date: 2022/10/12 15:12
* @param $dn
* @param $recursive //默认false,true为递归删除多个
* @return bool TRUE on success, FALSE on failure
*/
public function myldap_delete($dn, $recursive = false):bool
{
if($recursive == false){
$result = @ldap_delete($this->ldapconn, $dn);
if(!$result)
return false;
return $result;
}else{
//搜索子节点
$sr = @ldap_list($this->ldapconn, $dn,"ObjectClass=*",[""]);
if(!$sr){
error(200, $this->errorCode->codeMsg($this->ldapconn));
}
$info = ldap_get_entries($this->ldapconn, $sr);
for($i=0; $i < $info['count']; $i++){
//递归删除子节点
$result = $this->myldap_delete($info[$i]['dn'], $recursive);
if(!$result){
//如果删除失败,则返回结果
return($result);
}
}
return $this->myldap_delete($dn);
}
}
/**
* dec: php8.0版本 ldap_connect返回的是一个资源,并非是实例对象
*/
public function close()
{
//@ldap_unbind($this->ldapconn);
@ldap_close($this->ldapconn);
}
/**
* name: 用新值替换属性值
* @param $dn
* @param $entry ['uid'=>[] (删除掉mail属性(一些字段不允许删除)), 'mail'=>["9527@qq.com"] (添加或替换mail属性)]
* @param $controls
* @return bool
*/
public function myldap_mod_replace($dn, $entry, $controls=null)
{
if($this->myldap_detail($dn) != false){
$res = ldap_mod_replace($this->ldapconn, $dn, $entry, $controls);
if(!$res){
error(200, $this->errorCode->codeMsg($this->ldapconn));
}
return true;
}
return false;
}
/**
* name: 修改密码
* Date: 2022/10/12 17:51
* @param $dn
* @param $pwd //明文
* @return bool
*/
public function myldap_pwd($dn, $pwd)
{
$entry['userpassword'] = ["{MD5}".base64_encode(md5($pwd,true))];
return $this->myldap_mod_replace($dn, $entry);
}
/**
* name: 修改条目的名称(迁移)
* @param $dn //老的dn。如
cn=mali,cn=admin,dc=example,dc=org
* @param $newRdn //新的rdn。如
cn=newMali
* @param $newParent //新的上级dn
* @param $deleteOldRdn //老的dn 是否需要删除 true删除 false不删除
* @return bool
*/
public function myldap_rename($dn, $newRdn, $newParent, $deleteOldRdn=false)
{
if($this->myldap_detail($dn) != false && $this->myldap_detail($newRdn.','.$newParent) == false){
return ldap_rename($this->ldapconn, $dn, $newRdn, $newParent, $deleteOldRdn);
}
return false;
}
}
最后
以上就是正直眼神为你收集整理的Hyperf连接LDAP服务的全部内容,希望文章能够帮你解决Hyperf连接LDAP服务所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复