2012-12-23 39 views
2

我已經在這裏呆了幾天了。我嘗試了各種解決方案無濟於事。請幫忙...使用PHP/COM/ADSI/LDAP更改AD密碼

問題:我們有兩個域控制器,這些都不在我們的管理之下。我們可以通過端口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('[email protected]') 
#1 {main} - <b>Source:</b> Unknown<br/><b>Description:</b> Unknown" 
DETAILS -> "An Error Occurred." 

上面的代碼是在IIS Web服務器上的PHP文檔是由用戶可觀看頁面通過HTTPS稱爲

您能提供任何建議或指導?

+1

我敢肯定,AD是相當挑剔不設置密碼發生的信息通過明文LDAP。您需要他們通過LDAP啓用SSL。 – geoffc

+1

你有沒有試過phpLdapAdmin? –

+0

**更新12月29日12:16:46 **我已經能夠證明'新的COM(「LDAP:」)'成功地初始化和'$ ADSI-> OpenDSObject'成功地打開AD對象。我已經嘗試過其他用戶的AD帳戶和腳本失敗在同一行** ** 12月29日在17:57 **已取代'$用戶 - > SetPassword($ newPword1);'用'用戶 - >放(「pwdLastSet」,0);'併成功更新了相應的AD屬性。因此,這表明ADSI連接正在工作 – ChrisM

回答

1

我正在做同樣的事情,現在已經得到它的工作,至少在針對Server 2k8R2 DC時。

我不知道爲什麼你得到我發現有用的故障,您不過是幾件事情是:

1)在你趕上()處理程序檢索SetPassword返回的錯誤() ,處理和如下

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

然後看你能不能找到它上市here顯示。你也可以找到this有幫助。

2)嘗試改變SetPassword()調用ChangePassword()。這要求您也輸入舊密碼,但對DC的特權要求不太嚴格。如果你可以得到它的工作,它可能暗示你SetPassword()的問題是你用來在OpenDSObject()調用中進行身份驗證的管理員帳戶在目標域上沒有足夠的權限。

雖然有關ChangePassword()的警告,但與SetPassword()不同,密碼策略是嚴格執行的。所以你需要考慮密碼的最小年齡和複雜度以及歷史。最後一個我沒有放棄。

非常好,伊恩。

+0

嗨伊恩, 感謝您的意見。作爲迴應:1)我將添加額外的錯誤代碼。從內存中返回的錯誤代碼不在selfADSI列表中,我認爲它是-215 ...但會檢查並確認它。 2)我正在使用的服務帳戶具有域管理員權限。一旦我得到代碼工作,這個級別將被降低到用戶對象的提升特權。來自權力的說明,嚴格檢查是爲了執行域密碼策略。我正在致力於SASL/GSS-API/Kerberos解決方案。將發佈代碼一次工作。你是如何得到你的工作的? – ChrisM

0

我發現您使用的操作系統對使用此代碼有直接影響。

我正在使用本地版本IIS(Windows 7 Enterprise,IIS 7.5)在我的桌面上進行開發工作,並一直運行到此未知錯誤。

但是,一旦我在實際服務器上測試了我的ADSI密碼重置代碼(Windows 服務器2008 R2),它的工作完美無瑕。


參考: 錯誤代碼我得到了(使用伊恩的回答)是0x80020009這似乎與此有關的問題:(Registering a dll returns 0x80020009 error

所以,無論是怎麼了?似乎更深比ADSI和PHP/COM。

注: 像聖油,我能夠使用ADSI連接查詢失敗,只有當我試圖用SetPassword()