很久沒寫 PowerShell,剛好有個需求暖暖身。

要變更 AD 密碼,最無腦的做法是找台 Windows 用該 AD 帳號登入,按 Ctrl-Alt-Del 然後點「變更密碼」:

那有沒有辦法不要切換 Windows 登入帳號,直接變更其他 AD 帳號的密碼?(例如:小編持有多個公用帳號的密碼,用自己的帳號登入 Windows,修改公用 AD 帳號的密碼)

試寫了一個 PowerShell 小工具來完成這項工作。操作程序為輸入 AD 帳號(若非當下主機所在網域,則可輸入 DomainName\AccountName)、原來的密碼、輸入兩次新密碼,完成密碼變更。

完整程式如下。原理為先建立 System.DirectoryServices.AccountManagement.PrincipalContext,用 AD 帳號名稱找到 UserPrincipal,呼叫 ChangePassword(String, String) 方法變更密碼。輸入密碼部分,則借用先前學過的 PowerShell 密碼字串加密技巧

$ErrorActionPreference = 'STOP'
Add-Type -AssemblyName System.DirectoryServices.AccountManagement 

Write-Host "AD 密碼修改工具" -ForegroundColor Yellow
Write-Host "==============" -ForegroundColor Yellow
$domain = [Environment]::GetEnvironmentVariable("USERDOMAIN")
$userId = Read-Host "AD 帳號"
$p = $userId.Split('\')
if ($p.Length -eq 2) {
	$domain = $p[0]
	$userId = $p[1]
}
function decSecString($secString) {
	$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($secString)
	return [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
}
$passwd = decSecString (Read-Host "請輸入原密碼" -AsSecureString)
$passwdNew = decSecString (Read-Host "請輸入新密碼" -AsSecureString)
$passwdConfirm = decSecString (Read-Host "請再輸一次新密碼" -AsSecureString)
if ($passwdNew -ne $passwdConfirm) {
	Write-Host "新舊密碼不符" -ForegroundColor Red
	return
}
try {
	$ctx = New-Object System.DirectoryServices.AccountManagement.PrincipalContext([System.DirectoryServices.AccountManagement.ContextType]::Domain, $domain, $userId, $passwd)
}
catch {
	Write-Host $error[0].Exception.Message -ForegroundColor Yellow
	return
}
try {
	$user = [System.DirectoryServices.AccountManagement.UserPrincipal]::FindByIdentity($ctx, [System.DirectoryServices.AccountManagement.IdentityType]::SamAccountName, $userId)
}
catch {
	Write-Host $error[0].Exception.Message -ForegroundColor Cyan
	$ctx.Dispose()
	return
}
try {
	$user.ChangePassword($passwd, $passwdNew)
	Write-Host "密碼更新完畢" -ForegroundColor Green
}
catch {
	Write-Host $error[0].Exception.Message -ForegroundColor Magenta
}
$user.Dispose()
$ctx.Dispose()

變更成功的案例:

示範輸入不存在 AD 帳號、舊密碼不對、新密碼不符複雜度要求、新密碼兩次輸入不同時的顯示:

Example of using PowerShell to change AD password.


Comments

# by 小黑

請問黑哥都用啥編輯器撰寫PowerShell?VSCode?

# by Jeffrey

to 小黑,主要是 VSCode,簡單程式有時直接用 Notepad++。

# by Leo

請問黑大,Powershell 可否做成網頁版,讓用戶在外網先登入才再修改? 另外,下方 Captcha 出來的結果是會有誤嗎?剛看到 "70+30=",我輸入 100 然後跳出來說錯誤啊‧‧‧

# by Jeffrey

to Leo, 同樣邏輯翻寫成 ASPX 網頁不難,但對外提供 AD 登入容易變成駭客 Try 密碼或故意猜錯鎖帳號的管道,務必謹慎為之。 我也遇過 Captcha 偶爾秀斗,但頻率不高,所以就照慣例選擇裝死中 XD

# by Leo

To 黑大, 明白把這個變更密碼對外開放,是極高風險,但因現時 WFH 的情況多了,所以當需要修改 AD 密碼時便需要經網頁版進行。 我們之前寫的一個網頁版,是需要先登入,才可以修改 AD 密碼,但好像不是常常成功,或許是因為沒法判斷新修改的密碼不符那一項密碼規則,所以常常被客訴變更密碼很困難。

# by Vincent

To Leo WFH用Passwords Remote Desktop變更密碼會不會比較方便? http://woshub.com/change-user-password-rdp-session-windows/

# by Vincent

To Leo 更正一下網址http://woshub.com/allow-users-to-reset-expired-password-via-rd-webaccess-windows-server-2012/

# by 小C

請問,如果電腦使用者權限被鎖死(譬如:無法安裝程式、usb槽無法使用…等),有辦法改變權限使用嗎?

# by Leo

To 小C 那就是你所使用的電腦已被 Group Policy 限制了權限吧,這個是管理問題而非技術問題了。

# by 小C

To:Leo 嗯,沒錯,是被管理員限制。 只是在想有沒有簡便的方式可以去將usb權限開啟。 還是要謝謝您

# by Jeffrey

to Leo, 若屬刻意設定的限制,三兩下被破解,系統管理人員就要飛高高了。

# by Ken

請教~執行時訊息關閉太快看不見狀態(變更成功或密碼錯誤),因為無法在command或powershell之下執行,可以怎麼處理?(視窗中執行)

# by Jeffrey

to Ken, 試試在.ps1 的 return 上方加一行 Read-Host 應可做到按 Enter 再結束的效果。

# by Jackson2747

如我是 AD 管理者,怎麼 overwrite 密碼?

# by Jeffrey

to Jackson2747, Set-ADAccountPassword -Reset ,語法參考 https://learn.microsoft.com/en-us/powershell/module/activedirectory/set-adaccountpassword?view=windowsserver2022-ps#example-1-set-a-password-for-a-user-account-using-a-distinguished-name

Post a comment