使用PHP / COM / ADSI / LDAP更改AD密码

时间:2012-12-23 14:11:12

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

我已经被这几天困住了。我尝试了各种解决方案无济于事。请帮忙......

问题:我们有两个域控制器,不在我们的管理之下。我们可以通过端口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->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上的用户可查看页面调用

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

2 个答案:

答案 0 :(得分:1)

我做了几乎相同的事情,现在让它工作,至少在针对服务器2k8R2 DC时。

我不确定你为什么会失败,但我发现有些事情是有帮助的:

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

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

然后看看你是否可以找到here列出的内容。您可能还会发现this有帮助。

2)尝试改变对ChangePassword()的SetPassword()调用。这要求您输入旧密码,但对DC的权限要求不那么严格。如果你可以让它工作,它可能表明你的SetPassword()问题是你在OpenDSObject()调用中用于验证的管理员帐户在目标域上没有足够的权限。

关于ChangePassword()的警告,与SetPassword()不同,严格执行密码策略。因此,您需要考虑最小密码年龄和复杂性以及历史记录等内容。我最后一次失败了。

非常好运,Ian。

答案 1 :(得分:0)

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

我使用本地版本的IIS(Windows 7企业版,IIS 7.5)在桌面上进行开发工作,并一直遇到此未知错误。

然而,一旦我在实际服务器上测试了我的ADSI密码重置代码(Windows Server 2008 R2),它完美无缺。

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

所以出现问题似乎比ADSI和PHP / COM更深。

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