使用 Windows 整合驗驗的網站有時會接到使用者反映他們無法用 AD 帳號登入,常見原因有記錯密碼、帳號被鎖、密碼到期... 等等,另外也曾遇過一些罕見案例是與 Domain Controller 間網路不通、電腦時鐘不對。 處理 AD 帳號無法登入 SOP 的第一步應先排除常見的帳號被鎖、密碼過期等狀況再花時間調查,就像除濕機、微波爐、電視機的使用手冊最後都有張常見故障排除表,叫你先檢查電源線有沒有插、開關有沒開一樣,避免大家在低級錯誤上虛耗時間。

查詢 AD 帳號資訊多要靠網管人員操作 UI 找帳號看狀態,我花了點時間寫了以下 PowerShell 讓 SOP 最佳化,不需要開管理介面滑鼠,下指令敲帳號兩秒便知結果,就叫它「AD 帳號問題快篩」吧!

param (   
    [Parameter(Mandatory=$True)]
    [string] $userId 
)
$dc = "company-domain.com"
Write-Host "*** AD 帳號問題快篩 Ver 1.0***" -ForegroundColor Yellow
$ErrorActionPreference = "STOP"
$match = [System.Text.RegularExpressions.Regex]::Match($userId, "^(?<d>.+)\\(?<u>.+)`$")
if (!$match.Success) {
    Write-Host "請輸入 DomainName\UserId 帳號格式"
    Exit
}
$domain = $match.Groups["d"].Value
$userId = $match.Groups["u"].Value
try 
{
    [string]$svr = (Get-ADDomainController -Discover -Domain "$domain.$dc").HostName
    $user = Get-ADUser $userId -Properties LockedOut,LastLogonDate,PasswordLastSet,PasswordNeverExpires,msDS-UserPasswordExpiryTimeComputed -Server $svr
}
catch 
{
    Write-Host "找不到使用者 - $userId" 
    Exit
}

function Print([string]$label, [string]$value, $pass = $null) {
    Write-Host "$($label): " -ForegroundColor Cyan -NoNewline
    $color = [ConsoleColor]::White
    if ($null -ne $pass) {
        if ($pass -eq $true) { $color = [System.ConsoleColor]::Green }
        else { $color = [ConsoleColor]::Red }
    }
    Write-Host $value -ForegroundColor $color
}

function ToYN([bool]$bool) {
    if ($bool) {
        return "是"
    }
    return "否"
}
Print "登入帳號" $user.SamAccountName
Print "帳號名稱" "$($user.Name) / $($user.GivenName)"
Print "上次登入" $user.LastLogonDate.ToString("yyyy-MM-dd HH:mm:ss")
Print "是否啟用" (ToYN $user.Enabled) -pass ($user.Enabled)
Print "是否鎖定" (ToYN $user.LockedOut) -pass (!$user.LockedOut)
[DateTime]$lastPwdSet = $user.PasswordLastSet 
Print "上次密碼修改" $lastPwdSet.ToString("yyyy-MM-dd HH:mm:ss")
if (!$user.PasswordNeverExpires) 
{
    [DateTime]$nextChgDate = [DateTime]::FromFileTime($user."msDS-UserPasswordExpiryTimeComputed")
    [timespan]$timeLeft = $nextChgDate - [DateTime]::Now

    Print "密碼到期日" $nextChgDate.ToString("yyyy-MM-dd HH:mm:ss") -pass ($timeLeft.TotalSeconds -gt 0)
    Write-Host "密碼到期提示: " -NoNewline -ForegroundColor Cyan
    if ($timeLeft.TotalSeconds -lt 0) 
    {
        Write-Host "密碼己於 $($nextChgDate.ToString("yyyy-MM-dd HH:mm:ss")) 到期]" -ForegroundColor Red
    }
    else {
        $color = [ConsoleColor]::Yellow
        [int]$daysLeft = $timeLeft.TotalDays
        if ($daysLeft -le 7) { $color = [ConsoleColor]::Magenta }
        Write-Host "密碼還有 $($daysLeft) 天到期" -ForegroundColor $color
    }
}
else {
    Write-Host "** 密碼永久有效 **" -ForegroundColor Magenta
}

執行結果如下,輸入「網域名稱\AD帳號」即會顯示帳號是否啟用、是否被鎖定、上次登入時間、上次密碼修改時間、密碼到期時間等,方便先排除 AD 常見問題再進一步追查,有需要的朋友請自取。

A PowerShell script example to check AD account status (enabled, lockedOut, password expired) quickly.


Comments

# by Eric

老大 請問這個有辦法同時也取得最近或是最後一次登入的電腦名稱嗎

# by Jeffrey

to Eric, 我只有看過抓每台電腦最後登入者,跟你想做的有點落差 https://social.technet.microsoft.com/Forums/en-US/859384b1-6ec0-449c-bb2e-ad1f22e8e912/get-last-logon-timecomputer-and-username-together-with-powershell?forum=winserverpowershell

# by Jason

請問 我在$dc = "company-domain.com",這段設定了網域DomainName,在實際執行輸入尋找網域名稱\AD帳號,會找不到使用者?,是沒有連動到網域嗎 謝謝

# by Jeffrey

to Jason, $dc 之後會用於 Get-ADDomainController -Discover -Domain "$domain.$dc",我建議先把 "$domain.$dc" 換成你們公司的網域名稱手動測試,成功後再對映出 $domain 與 $dc 的值。

# by 艾里克斯

也可用 net user /domain [Account]

# by metavige

以我們公司為例,我們公司的 $domain 與 $dc 的最前面一段是重複的 舉例,像是我們公司可能是 "abc.com.corp", domain 是 "abc" 我把 Get-ADDomainController -Discover -Domain "$domain.$dc" 改成 Get-ADDomainController -Discover -Domain "$dc" 就可以用了

# by Neo Chen

感謝您的程式,我修改了一下換成用Email來查詢。 您的這一段程式真的給了我很好的靈感!

# by Alex

To Jason 可能是沒有此 Feature, 試試輸入以下指令: Import-Module ServerManager Add-WindowsFeature RSAT-AD-PowerShell Import-Module ActiveDirectory

# by Arthur

感謝您的分享

# by wayneT

謝謝你的分享,很實用的好工具。

# by Paul

實用 感謝分享

# by leosedward

請問這個可以改寫為解鎖帳號的網頁?

# by Jeffrey

to leosedward,.NET 有 API 可以解鎖 https://learn.microsoft.com/en-us/dotnet/api/system.directoryservices.accountmanagement.authenticableprincipal.unlockaccount?view=dotnet-plat-ext-7.0 但解鎖需要用較高權限的帳號執行,要審慎設計以免變成資安漏洞。

Post a comment