简体   繁体   English

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

[英]Change AD Password using PHP/COM/ADSI/LDAP

I've been stumped on this for a couple days now. 我已经为此困扰了几天。 I've tried various solutions to no avail. 我尝试了各种解决方案都无济于事。 Please help... 请帮忙...

Problem: We have two domain controller, which are not under our management. 问题:我们有两个域控制器,它们不在我们的管理之下。 We are able to connect via LDAP on port 389, but are not able to connect securely over port 636. 我们能够通过LDAP在端口389上进行连接,但无法通过端口636安全地进行连接。

We are developing a system to allow a number of self-service facilities, one of which is a password recovery tool. 我们正在开发一种允许许多自助服务设施的系统,其中之一是密码恢复工具。 This works up to the point of resetting the users password. 这可以达到重置用户密码的目的。

I have found some code via the PHP manual which appears to do what we need, but cant seem to get it to work. 我已经通过PHP手册找到了一些代码,该代码似乎可以满足我们的需要,但似乎无法正常工作。

This is the code I have thus far 这是我到目前为止的代码

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";
    }
}

In testing $result["object"] returns "Success". 在测试中, $result["object"]返回“成功”。 But the code seems to fail on the $user->SetPassword($newPword1); 但是代码似乎在$user->SetPassword($newPword1);上失败$user->SetPassword($newPword1); line. 线。

The error that is being returned is: 返回的错误是:

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."

The above code is in a php doc on an IIS Web Server which is called by a user viewable page over https 上面的代码在IIS Web服务器上的php文档中,由用户通过https查看的页面调用

Are you able to offer any advice or guidance? 您可以提供任何建议或指导吗?

I'm doing pretty much the same thing and have now got it to work, at least when targeting a Server 2k8R2 DC. 我正在做几乎相同的事情,并且现在至少在将服务器2k8R2 DC作为目标时,它已经可以正常工作。

I'm not sure why you're getting the failure you are but a couple of things I've found helpful are: 我不确定您为什么会失败,但是我发现有两点有用:

1) In your catch() handler retrieve the error returned from SetPassword(), process and display it as follows 1)在您的catch()处理函数中,检索从SetPassword()返回的错误,进行处理并显示如下

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

Then see if you can find it listed here . 然后查看是否可以在此处找到它。 You may also find this helpful. 您可能还会发现很有帮助。

2) Try varying the SetPassword() call to ChangePassword(). 2)尝试将SetPassword()调用更改为ChangePassword()。 This requires that you enter the old password too but has less stringent privilege requirements on the DC. 这要求您也输入旧密码,但是对DC的权限要求不那么严格。 If you can get that to work it could suggest that your problem with SetPassword() is that the admin account you're using to authenticate in the OpenDSObject() call does not have sufficient privileges on the target domain. 如果您可以使用它,则可能表明SetPassword()的问题在于您用于OpenDSObject()调用中进行身份验证的管理员帐户在目标域上没有足够的特权。

A word of warning though about ChangePassword() which is that, unlike SetPassword(), password policy is strictly enforced. 关于ChangePassword()的警告是,与SetPassword()不同的是,严格执行密码策略。 So you need to take account of things like minimum password age and complexity, and also history. 因此,您需要考虑诸如最小密码使用期限和复杂性以及历史记录之类的问题。 I came unstuck on that last one. 我没有被遗忘在最后一个。

Very best of luck with it, Ian. 祝您好运,伊恩。

I've found that the OS you're using has a direct impact on using this code. 我发现您使用的操作系统对使用此代码有直接影响。

I was doing my development work on my desktop using a local version IIS (Windows 7 Enterprise, IIS 7.5) and kept running into this unknown error. 我正在使用本地版本的IIS(Windows 7 Enterprise,IIS 7.5)在桌面上进行开发工作,并且一直遇到此未知错误。

However, Once I tested my ADSI password reset code on an actual server (Windows Server 2008 R2), it worked flawlessly. 但是,一旦我在实际服务器(Windows Server 2008 R2)上测试了ADSI密码重置代码,它就可以正常工作。


For reference: The error code I got (using Ian's answer) was 0x80020009 which appears to be related to this question: ( Registering a dll returns 0x80020009 error ) 供参考:我得到的错误代码(使用Ian的答案)是0x80020009,这似乎与以下问题有关:( 注册dll返回0x80020009错误

So whatever is going wrong appears to be deeper than ADSI and PHP/COM. 因此,出了什么问题似乎比ADSI和PHP / COM更深入。

NOTE: Like ChrisM, I was able to use the ADSI connection to query information the failure only occurred when I tried to use SetPassword() 注意:像ChrisM一样,我能够使用ADSI连接来查询仅在尝试使用SetPassword()时发生失败的信息

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM