当我的计算机不是域成员时,非管理员如何使用 PowerShell 更改活动目录密码?

How can I, a non-administrator, change my active directory password using PowerShell, when my computer is not a member of the domain?

我以非域用户身份登录笔记本电脑。

我使用 Open VPN 连接到远程网络,并且可以通过该 VPN 访问域资源,例如 CIFS 共享,方法是在出现提示时输入我的域凭据。

我想使用 PowerShell 更改我在远程域上的密码。

我将我当前的凭据存储为 $credentials,一个 System.Management.Automation.PSCredential 对象。

我将新密码存储为 $newPassword,一个安全字符串,

当我的计算机不是域的成员时,我作为非管理员如何使用 PowerShell 更改我的 Active Directory 密码?

域的 FQDN d0-ad.domain.com 解析为域控制器 IP 地址。 我已将 netbios 名称 NP-DOMAIN 添加到主机文件,因此它也解析为域控制器。

这是我遇到问题的脚本部分:

Write-Verbose "Setting up DirectoryEntry object"
$DomainEntry = New-Object -TypeName System.DirectoryServices.DirectoryEntry "LDAP://$($netBiosName)" ,$credentials.UserName,$($credentials.GetNetworkCredential().password)

Write-Verbose "Setting up DirectorySearcher object"
$Searcher = New-Object -TypeName System.DirectoryServices.DirectorySearcher

$Searcher.SearchRoot = $DomainEntry

$userName = $($credentials.UserName).Replace("$($netBiosName)\","")
Write-Verbose "Username set as $($userName)"
$Searcher.Filter = "(samaccountname=$($userName))"

$user = $Searcher.FindOne()

$userObject = [ADSI]$user.Path

if ($userObject) {
    Write-Verbose "Changing password for user: $($user.Path)"
    $userObject.ChangePassword($credentials.GetNetworkCredential().password, [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($NewPassword)))
} else {
    Write-Verbose "User $($username) not found"
    throw "User $($username) not found"
}

问题出现在

$userObject = [ADSI]$user.Path

如果我尝试访问 $userObject,我会收到错误消息:

format-default : The following exception occurred while retrieving member "distinguishedName": "A local error has occurred. " + CategoryInfo : NotSpecified: (:) [format-default], ExtendedTypeSystemException + FullyQualifiedErrorId : CatchFromBaseGetMember,Microsoft.PowerShell.Commands.FormatDefaultCommand

我知道凭据是正确的并且与目录的连接有效,因为 $Searcher.FindOne() 方法正确搜索、查找并 returns 正确的用户。

那为什么我得到 "A local error has occurred."?

这个错误看起来很奇怪,但我认为这可能是因为您没有提供正确的凭据。 [ADSI] 类型加速器只是一个 shorthand 用于创建 DirectoryEntry 对象。所以 [ADSI]$user.Path 相当于创建一个 DirectoryEntry 就像你在代码顶部所做的那样,只是没有用户名和密码。

所以你可以:

  1. 像在文件顶部那样创建它:
$userObject = New-Object -TypeName System.DirectoryServices.DirectoryEntry $user.Path, $credentials.UserName, $($credentials.GetNetworkCredential().password)

或者,

  1. SearchResult 上致电 GetDirectoryEntry()DirectoryEntry 对象 returns 将设置与 SearchRoot 上相同的凭据:
$userObject = $user.GetDirectoryEntry()