【问题标题】:Change AD Password using PHP/COM/ADSI/LDAP使用 PHP/COM/ADSI/LDAP 更改 AD 密码
【发布时间】:2012-12-10 07:14:55
【问题描述】:

我已经为此困扰了几天。我尝试了各种解决方案均无济于事。请帮忙...

问题:我们有两个域控制器,它们不在我们的管理之下。我们能够通过端口 389 上的 LDAP 进行连接,但无法通过端口 636 安全地连接。

我们正在开发一个系统,允许使用多种自助服务设施,其中之一是密码恢复工具。直到重置用户密码为止。

我找到了一些代码via the PHP manual,它似乎可以满足我们的需要,但似乎无法让它发挥作用。

这是我到目前为止的代码

if ($caller==="change"){
if (($newPword1 === NULL)||($newPword1 === "" )){ return false;}
if (($newPword2 === NULL)||($newPword2 === "" )){ return false;}
if ($newPword1 != $newPword2) {
  $result["ERROR"]="1";
  $result["DETAILS"]="Your new password and the confirmation must match!";
  exit();
}
try { 
    $adldap = new adLDAP(); 
} catch (adLDAPException $e) {
    $result["ERROR"]="1";
    $result["DETAILS"]="An error occurred in adLDAP";
    echo json_encode($result);
    exit();
}

$userinfo = $adldap->user()->info($username, array("givenname","dn","lockouttime"));
$res = $userinfo[0]["lockouttime"];
$userDN = $userinfo[0]["dn"];
$firstName = $userinfo[0]["givenname"];
$authUser = $adldap->authenticate($username,$currentPword);
if ($authUser){
    try {
        $adminUsername = $domain."\\".$adminUsername;
        $srvDN = "LDAP://".$server."/";

        try {
            $ADSI = new COM("LDAP:");
        } catch (exception $e){
            $result["ERROR"]="1";
            $result["ERRORmsg"]=$e->getMessage();
            echo json_encode($result);
            exit();
        }
        try {
            $user = $ADSI->OpenDSObject($srvDN.$userDN, $adminUsername, $adminPassword, 1);
        } catch (exception $e){
            $result["ERROR"]="2";
            $result["ERRORmsg"]= $e->getMessage();
            echo json_encode($result);
            exit();
        }
        try { //set password
            if ($user){
                $result["object"]="Success";
            } else {
                $result["object"]="Failed";
            }
            $user->SetPassword($newPword1);  //line:114 -> error occurring on this line
            $user->SetInfo();
            $result["ERROR"]="0";
            $result["DETAILS"]="Thank you $firstName[0]<br><strong>Your password has been changed</strong><br><br>This may take up to 30 minutes to take effect depending on your location";
        } catch (exception $e) {
            $result["ERROR"]="3";
            $result["ERRORmsg"]=$e." - ".$e->getMessage();
            $result["DETAILS"]="An Error Occurred.";
        }
        unset($user);
        unset($ADSI);
    } catch (exception $e){
        $result["ERROR"]="1";
        $result["DETAILS"]="An Error Occurred in the ADSI COM";
        echo json_encode($result);
        exit();
    }
} else {
    if ($res[0] != "0"){
        $result["ERROR"]="1";
        $result["DETAILS"]="Im sorry $firstName[0].<br>Your account is now locked.  Please contact the IT Service Desk for advice";
    } else {
        $result["ERROR"]="1";
        $result["DETAILS"]="Im sorry $firstName[0].<br>Your current password is incorrect";
    }
}

在测试中$result["object"] 返回“成功”。但是代码似乎在$user-&gt;SetPassword($newPword1); 行上失败了。

返回的错误是:

ERROR -> "3"
object -> "Success"
ERRORmsg -> "exception 'com_exception' with message '<b>Source:</b> Unknown<br/><b>Description:</b> Unknown' in C:\inetpub\wwwroot\<path>\<filename>.php:114
Stack trace:
#0 C:\inetpub\wwwroot\<path>\<filename>.php(114): variant->SetPassword('P@ssw0rd')
#1 {main} - <b>Source:</b> Unknown<br/><b>Description:</b> Unknown"
DETAILS -> "An Error Occurred."

以上代码位于 IIS Web 服务器上的 php 文档中,用户可通过 https 浏览页面调用该文档

您能提供任何建议或指导吗?

【问题讨论】:

  • 我很确定 AD 对于不在明文 LDAP 上设置密码非常挑剔。您需要它们来启用基于 LDAP 的 SSL。
  • 你试过phpLdapAdmin吗?
  • 2012 年 12 月 29 日 16:46 更新 我已经能够证明 new COM("LDAP:") 成功初始化和 $ADSI-&gt;OpenDSObject 成功打开 AD 对象。我已尝试针对其他用户 AD 帐户,但脚本在同一行失败 **2012 年 12 月 29 日 17:57 ** 已将 $user-&gt;SetPassword($newPword1); 替换为 $user-&gt;Put("pwdLastSet",0); 并成功更新了相应的 AD 属性。所以这表明 ADSI 连接正在工作
  • 有谁知道 GSS-API/Kerberos 是否允许我通过与 ldap_sasl 绑定来执行此操作?

标签: php iis active-directory adsi change-password


【解决方案1】:

我发现您使用的操作系统对使用此代码有直接影响。

我正在使用本地版本的 IIS(Windows 7 Enterprise、IIS 7.5)在我的桌面上进行开发工作,并且一直遇到这个未知错误。

但是,一旦我在实际服务器上测试了我的 ADSI 密码重置代码(Windows Server 2008 R2),它运行完美。


供参考: 我得到的错误代码(使用 Ian 的回答)是 0x80020009,这似乎与这个问题有关:(Registering a dll returns 0x80020009 error)

因此,出现问题的地方似乎比 ADSI 和 PHP/COM 更深。

注意: 像 ChrisM 一样,我能够使用 ADSI 连接来查询信息,只有在我尝试使用 SetPassword() 时才会发生故障

【讨论】:

    【解决方案2】:

    我正在做几乎相同的事情,现在已经开始工作了,至少在针对服务器 2k8R2 DC 时是这样。

    我不确定你为什么会失败,但我发现有几件事很有帮助:

    1) 在你的 catch() 处理程序中检索从 SetPassword() 返回的错误,处理并显示如下

    $rawErr = $e->getCode();
    $processedErr = $rawErr + 0x100000000;
    printf( 'Error code 0x%x', $processedErr );
    

    然后看看你能不能找到它列出的here。您可能还会发现 this 很有帮助。

    2) 尝试将 SetPassword() 调用更改为 ChangePassword()。这要求您也输入旧密码,但对 DC 的权限要求不那么严格。如果您可以使其正常工作,则可能表明您使用 SetPassword() 的问题是您用于在 OpenDSObject() 调用中进行身份验证的管理员帐户在目标域上没有足够的权限。

    关于 ChangePassword() 的警告是,与 SetPassword() 不同,密码策略是严格执行的。因此,您需要考虑最小密码年龄和复杂性以及历史记录等因素。我对最后一个不满意。

    祝你好运,伊恩。

    【讨论】:

    • 您好伊恩,感谢您的意见。作为回应:1)我将添加额外的错误代码。从内存中返回的错误代码不在selfADSI列表中,我认为它是-215 ...但会检查并确认这一点。 2) 我使用的服务帐户具有域管理员权限。一旦我让代码工作,这个级别将降低到对用户对象的提升特权。来自权力的指示,严格检查到位以执行域密码策略。我正在研究 SASL/GSS-API/Kerberos 解决方案。一旦工作将发布代码。你是如何让你的工作的?
    猜你喜欢
    • 2018-11-15
    • 1970-01-01
    • 2020-02-29
    • 1970-01-01
    • 2015-10-06
    • 1970-01-01
    • 2020-03-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多