1、需要ad服务器开启ca
2、ca打开http注册,下载根证书在本地开发机上注册
3、配置本地开发机的php.ini中的openssl开启
4、设置openssl,导入证书
php程序中设置

ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE,"D:\phpStudy\PHPTutorial\certnew.cer");
ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, 7);
putenv('LDAPTLS_REQCERT=never');

在php.ini中设定如下

extension=php_openssl.dll

[openssl]
; The location of a Certificate Authority (CA) file on the local filesystem
; to use when verifying the identity of SSL/TLS peers. Most users should
; not specify a value for this directive as PHP will attempt to use the
; OS-managed cert stores in its absence. If specified, this value may still
; be overridden on a per-stream basis via the "cafile" SSL stream context
; option.
openssl.cafile=D:\phpStudy\PHPTutorial\1.pem

; If openssl.cafile is not specified or if the CA file is not found, the
; directory pointed to by openssl.capath is searched for a suitable
; certificate. This value must be a correctly hashed certificate directory.
; Most users should not specify a value for this directive as PHP will
; attempt to use the OS-managed cert stores in its absence. If specified,
; this value may still be overridden on a per-stream basis via the "capath"
; SSL stream context option.
openssl.capath=D:\phpStudy\PHPTutorial

其中1.pem为ad服务器web端下载的ca证书cer转换pem
在线转换网址http://web.chacuo.net/netsslcer2pem
注意转换完后编码格式,UTF-8,Unix(LF)

//连接范例
        $host= 'ldaps://aaa.xxx.com';
        $port = '636';//一般都是389  636加密
        $domain = 'xxx.com';// 域
        $account = 'administrator';// 账号
        $password = 'abc123!';//域用户密码
        $user = "{$account}@{$domain}";// 域用户名 admin@domain
        $conn = ldap_connect($host, $port);
//连接范例
        $host= 'ldap://aaa.xxx.com';
        $port = '636';//一般都是389  636加密
        $domain = 'xxx.com';// 域
        $account = 'administrator';// 账号
        $password = 'abc123!';//域用户密码
        $user = "{$account}@{$domain}";// 域用户名 admin@domain
        $conn = ldap_connect($host, $port);
        ldap_start_tls($conn);

错误要点总结

ldap_bind(): Unable to bind to server: Can't contact LDAP server
无法bind,其实已经连接上ldap服务器,因ssl问题,无法绑定

Server is unwilling to perform

ldap_modify(): Modify: Constraint violation

如何修改密码?
最开始,决定用程序初始化/修改用户密码时遇到了问题,对一个测试用户右键查看属性,里面有字段userPassword,手工赋值后该密码并没有起到作用,通过查询国外文档,找到了原因所在:

根据下面文章,我们知道AD域将用户密码存储在unicodePwd属性中,而不是userPassword中,因此,在创建用户的时候,不需要给userPassword字段赋值;
unicodePwd属性不可查询,需要建立ssl安全通道才能进行修改,否则只能在服务器用**Set-ADAccountPassword -Identity 【DN】**修改;
方案1这里若域还没有配置安装证书服务,636安全端口不能连接,只能在AD域服务器跑powershell脚本对用户批量设置密码【已实现】
方案2若配置了安装证书服务,则使用self.conn.extend.microsoft.modify_password(dn, new_pwd, old_pwd)完成对密码的修改/初始化;

Active Directory中的LDAP密码更改
2010年8月26日/ 尼尔·威尔逊

我从未真正热衷于Active Directory。Microsoft倾向于将标准更像是建议而不是规则,而Active Directory则提供了一些很好的例子。最近有人问我一个问题,关于如何通过LDAP更改Active Directory中的密码。在大多数目录服务器中,您要么使用LDAP密码修改扩展操作(如RFC 3062中所述),要么执行简单的修改操作以将明文密码替换userPassword属性(服务器将自动执行任何操作)。必要的编码来掩盖该值)。但是,Active Directory有许多非常不寻常的要求,因此可能值得一提。它们包括:

Active Directory似乎不支持密码修改扩展操作,因此您必须使用常规LDAP修改操作来更改密码。
Active Directory将密码存储在unicodePwd属性中,而不是userPassword中。
Active Directory仅接受通过安全连接的密码更改。我只用过SSL。也许您也可以使用StartTLS或具有机密性的SASL,但是我不确定。
新密码必须用引号引起来,并且必须使用UTF-16 little-endian编码。
Active Directory可能会对密码施加一些强度要求,尽管这些要求的确切含义可能因一个实例而异。
知道了这些要求之后,您应该能够使用允许您在Active Directory中执行密码更改的任何LDAP API编写代码。

PHP修改AD密码范例

//重置默认密码
$pwdtxt = "123abc!";
$newPassword = '"' . $pwdtxt . '"';
$newPass = iconv('UTF-8', 'UTF-16LE', $newPassword);
$bindpwd["unicodepwd"] = $newPass;
$respwd=ldap_modify($conn, $base_dn,$bindpwd);
if(!$respwd){
   $arr['error']=ldap_error($conn);// 返回报错信息
   $arr['msg']='更改密码错误';
   $arr['bool']=false;
   ldap_close($conn);
   return $arr;
}

参考python修改密码
https://blog.csdn.net/qq_33997198/article/details/105297121