Windows XP Windows 7 Windows 2003 Windows Vista Windows 綜合教學 Linux 系統教學
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟體教學

VB.NET 程式設計:透過 ADSI 修改 Active Directory 使用者密碼

編輯:Windows Server 教學

開發環境需求

  • Visual Studio .NET (VB.NET)
  • 專案加入 COM 參考:Active DS Type Library (ActiveDs.tlb)
  • 目標框架:.NET Framework 1.1/2.0+

核心程式碼實作

輔助函式:轉換 DNS 網域名為 LDAP 路徑

Private Function GetDomainDN(ByVal dnsDomainName As String) As String
    ' 例:corp.contoso.com → DC=corp,DC=contoso,DC=com
    Dim parts() As String = dnsDomainName.Split("."c)
    Dim sb As New System.Text.StringBuilder()
    For i As Integer = 0 To parts.Length - 1
        If i > 0 Then sb.Append(",")
        sb.Append("DC=").Append(parts(i))
    Next
    Return sb.ToString()
End Function

主要功能:變更指定使用者密碼

Public Sub ChangeUserPassword( _
    ByVal domainDnsName As String, _
    ByVal userName As String, _
    ByVal ouPath As String, _          ' 例:"OU=Users,OU=Taipei"
    ByVal oldPassword As String, _
    ByVal newPassword As String)

    Try
        ' 建立 LDAP 路徑:LDAP://CN=Administrator,OU=Users,OU=Taipei,DC=corp,DC=contoso,DC=com
        Dim ldapPath As String = String.Format( _
            "LDAP://CN={0},{1},{2}", _
            userName, ouPath, GetDomainDN(domainDnsName))

        ' 繫結使用者物件 (使用目前執行緒認證)
        Dim user As ActiveDs.IADsUser = _
            DirectCast(GetObject(ldapPath), ActiveDs.IADsUser)

        ' 變更密碼 (需知舊密碼)
        user.ChangePassword(oldPassword, newPassword)
        user.SetInfo()  ' 送交變更

        MessageBox.Show("密碼變更成功")

    Catch ex As System.Runtime.InteropServices.COMException
        ' ADSI 錯誤代碼處理
        Select Case ex.ErrorCode
            Case &H8007052D  ' ERROR_LOGON_FAILURE
                Throw New Exception("舊密碼錯誤或帳號鎖定")
            Case &H80070005  ' E_ACCESSDENIED
                Throw New Exception("權限不足:需具備「重設密碼」或「變更密碼」權限")
            Case &H8007202F  ' 密碼不符合原則
                Throw New Exception("新密碼不符合網域密碼原則 (長度、複雜度、歷程記錄)")
            Case Else
                Throw New Exception(String.Format("ADSI 錯誤 0x{0:X}: {1}", ex.ErrorCode, ex.Message))
        End Select

    Catch ex As Exception
        Throw New Exception("發生未預期錯誤: " & ex.Message)
    End Try
End Sub

呼叫範例

Private Sub btnChangePwd_Click(sender As Object, e As EventArgs) Handles btnChangePwd.Click
    Try
        ChangeUserPassword( _
            domainDnsName:="corp.contoso.com", _
            userName:="jdoe", _
            ouPath:="OU=Users,OU=Taipei", _
            oldPassword:=txtOldPwd.Text, _
            newPassword:=txtNewPwd.Text)
    Catch ex As Exception
        MessageBox.Show(ex.Message, "錯誤", MessageBoxButtons.OK, MessageBoxIcon.Error)
    End Try
End Sub

進階議題與最佳實務

1. 重設密碼 vs 變更密碼

操作方法權限需求適用情境
變更密碼IADsUser.ChangePassword使用者自身、需知舊密碼使用者自助變更
重設密碼IADsUser.SetPassword管理員 (Reset Password 權限)管理員解鎖/重設、服務帳號輪換

2. 安全性強化建議

  • **傳輸加密**:生產環境強制使用 LDAPS (LDAP:// → LDAPS://) 或 StartTLS
  • **認證隔離**:避免硬編碼管理員帳密,使用 Windows 整合驗證或憑證式驗證
  • **輸入驗證**:檢查新密碼複雜度、長度、禁止字元,減少 AD 拒絕往返
  • **稽核記錄**:記錄變更操作 (誰、何時、哪帳號),符合合規需求

3. 常見錯誤代碼對照表

HRESULT常數名稱說明
0x8007052DERROR_LOGON_FAILURE舊密碼錯誤、帳號停用/鎖定/過期
0x80070005E_ACCESSDENIED權限不足 (ACL 未授予 Change/Reset Password)
0x8007202F-密碼違反網域原則 (歷程、長度、複雜度)
0x8007203A-密碼太短
0x8000500DE_ADS_PROPERTY_NOT_SET屬性未設定 (如嘗試 SetPassword 於未啟用帳號)

4. 替代方案:System.DirectoryServices (純 .NET)

Imports System.DirectoryServices

Dim entry As New DirectoryEntry( _
    "LDAP://CN=jdoe,OU=Users,DC=corp,DC=contoso,DC=com", _
    Nothing, Nothing, AuthenticationTypes.Secure)
entry.Invoke("ChangePassword", oldPwd, newPwd)
entry.CommitChanges()

System.DirectoryServices 為 .NET 原生封裝,無需 COM Interop,效能與部署較佳,建議新專案優先採用。

Copyright © Windows教程網 All Rights Reserved