2

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

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

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

通过 PHP 手册找到了一些代码,这些代码似乎可以满足我们的需要,但似乎无法使其正常工作。

这是我到目前为止的代码

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 的可查看页面调用

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

4

2 回答 2

1

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

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

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

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

然后看看你能不能在这里找到它。您可能还会发现很有帮助。

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

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

祝你好运,伊恩。

于 2013-01-12T17:55:52.153 回答
0

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

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

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


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

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

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

于 2017-08-15T17:18:22.093 回答