Перевірте, чи введений пароль користувача в сценарії Powershell


30

Я працюю зі сценарієм Powershell, який додає заплановані завдання системам нашого домену. Коли я запускаю цей сценарій, він запропонує мені пароль. Я іноді жирним пальцем пароль і процес починається, що блокує мій рахунок. Чи є спосіб перевірити свої облікові дані, щоб переконатися, що те, що я ввів, буде підтверджено в домені?

Я хотів би знайти спосіб запиту контролера домену. Я здійснив кілька пошукових запитів у Google, і я мав би змогу виконати WMI-запит та пастку для помилки. Я хотів би уникнути цього стилю перевірки, якщо це можливо.

Якісь ідеї? Заздалегідь спасибі.

Відповіді:


26

У мене це є у моїй бібліотеці:

$cred = Get-Credential #Read credentials
 $username = $cred.username
 $password = $cred.GetNetworkCredential().password

 # Get current domain using logged-on user's credentials
 $CurrentDomain = "LDAP://" + ([ADSI]"").distinguishedName
 $domain = New-Object System.DirectoryServices.DirectoryEntry($CurrentDomain,$UserName,$Password)

if ($domain.name -eq $null)
{
 write-host "Authentication failed - please verify your username and password."
 exit #terminate the script.
}
else
{
 write-host "Successfully authenticated with domain $domain.name"
}

1
Якщо я не помиляюся, це в кінцевому підсумку надішле пароль простим текстом по всій мережі, правда? Якщо це так, то я маю рацію припускати, що AccountManagement.PrincipalContext.ValidateCredentials()це не так (якщо ви вказали захисну нитку для пароля)?
Code Jockey

Чому ви не використовуєте ActiveDirectoryмодуль для запиту LDAP?
Калонь Колоб

6 років тому не було активного модуля каталогів
Jim B

Цей сценарій також допомагає у випадках, коли ви не можете встановити модулі AD PowerShell з тих чи інших причин.
Dodzi Dzakuma

16

Це те, що я використовував у минулому; він повинен працювати для локальних облікових записів машин та "каталогу додатків", але поки що я його успішно використовую лише з обліковими записами AD:

    function Test-Credential {
    <#
    .SYNOPSIS
        Takes a PSCredential object and validates it against the domain (or local machine, or ADAM instance).

    .PARAMETER cred
        A PScredential object with the username/password you wish to test. Typically this is generated using the Get-Credential cmdlet. Accepts pipeline input.

    .PARAMETER context
        An optional parameter specifying what type of credential this is. Possible values are 'Domain','Machine',and 'ApplicationDirectory.' The default is 'Domain.'

    .OUTPUTS
        A boolean, indicating whether the credentials were successfully validated.

    #>
    param(
        [parameter(Mandatory=$true,ValueFromPipeline=$true)]
        [System.Management.Automation.PSCredential]$credential,
        [parameter()][validateset('Domain','Machine','ApplicationDirectory')]
        [string]$context = 'Domain'
    )
    begin {
        Add-Type -assemblyname system.DirectoryServices.accountmanagement
        $DS = New-Object System.DirectoryServices.AccountManagement.PrincipalContext([System.DirectoryServices.AccountManagement.ContextType]::$context) 
    }
    process {
        $DS.ValidateCredentials($credential.UserName, $credential.GetNetworkCredential().password)
    }
}

Я хотів би почути, якщо хтось помітить це - я вважаю, що коли я використовую ValidateCredentials () таким чином з неправильним паролем, це, здається, викликає дві (2) помилкові спроби пароля - я не можу контролювати кількість порогу спроб на нашому домені, і він низький, тому я вважаю за краще не мати двох поганих спроб, коли я здійснюю один дзвінок ... може хтось також це бачить?
Code Jockey

Ви використовуєте формат домена \ користувача або UPN (користувач @ домен)? Я не в змозі повторити це, але наступна URL-адреса описує подібну проблему: social.msdn.microsoft.com/Forums/vstudio/en-US/…
jbsmith

Ви повинні мати можливість просто передати $contextяк аргумент конструктору. PowerShell автоматично перетворить рядки в перерахунок. А ще краще, просто зробіть [System.DirectoryServices.AccountManagement.ContextType]тип $context. Крім того, для чого ви використовуєте beginі processтут? Трубопровід видається дивним способом використання цієї функції.
jpmc26

@ jpmc26: введення $contextпараметра [System.DirectoryServices.AccountManagement.ContextType]не є опцією, оскільки збірка, що містить, не завантажується доти, доки не буде виконано тіло функції ; використання конвеєра корисно, якщо ви хочете перевірити кілька облікових даних.
mklement

@mklement Немає причини, щоб Add-Typeвиклик не можна було перенести за межі функції, до того, як буде визначено його визначення. Я вагаюсь, щоб Add-Typeвиклик беззастережно виконувався повторно всередині функції, навіть якщо він уже завантажений. Перевірка декількох облікових даних одночасно здається дивним випадком. У рідкісному випадку саме цього ви хочете, ви можете легко завершити виклик ForEach-Object, тому я не бачу причин ускладнювати функцію.
jpmc26

1

Я вважаю цю публікацію корисною, однак вона не вирішила мою проблему, оскільки я намагався запустити її зі сценарію з увімкненим локальним обліковим записом адміністратора. Схоже, він не працює як локальний адміністратор (лише при вході в систему як користувач домену).

Однак мені нарешті вдалося отримати робоче рішення, і оскільки це було так багато проблем, я подумав, що поділюсь тут, тому хтось із цією проблемою отримає відповідь саме тут. Обидві відповіді на одній сторінці залежно від ваших потреб.

Зауважте, що вище в scipt (не включений сюди, оскільки це лише розділ отримання облікових даних) встановлено powergui і є вимогою до цього коду нижче (а також рядка "Add-PSSnapin Quest.ActiveRoles.ADManagement"). Не впевнений, що робить powergui, це інше, але ніхто інший не міг мені сказати, і це працює.

Підпишіть своє власне доменне ім’я у розділах "ім'я домену".

#Get credentials
$credential_ok = 0
while ($credential_ok -ne 1)
{
    $credential = get-credential
    $result = connect-qadservice -service *domain_name* -credential $credential
    [string]$result_string = $result.domain
    if ($result_string -eq "*domain_name*")
    {
        $credential_ok = 1
        #authenticated
    }
    else
    {
        #failed
    }     
}
$username = $credential.username 
$password = $credential.GetNetworkCredential().password 

$date = get-date
Add-Content "c:\lbin\Install_log.txt" "Successfully authenticated XP script as $username $date"

1

(поки що) Ще одна версія:

param([string]$preloadServiceAccountUserName = "")

function HarvestCredentials()
{

        [System.Management.Automation.PSCredential]$credentialsOfCurrentUser = Get-Credential -Message "Please enter your username & password" -UserName $preloadServiceAccountUserName

        if ( $credentialsOfCurrentUser )
        {
            $credentialsOfCurrentUser = $credentialsOfCurrentUser
        }
        else
        {
            throw [System.ArgumentOutOfRangeException] "Gui credentials not entered correctly"          
        }

    Try
    {


        # see https://msdn.microsoft.com/en-us/library/system.directoryservices.directoryentry.path(v=vs.110).aspx
        # validate the credentials are legitimate
        $validateCredentialsTest = (new-object System.DirectoryServices.DirectoryEntry ("WinNT://"+$credentialsOfCurrentUser.GetNetworkCredential().Domain), $credentialsOfCurrentUser.GetNetworkCredential().UserName, $credentialsOfCurrentUser.GetNetworkCredential().Password).psbase.name
        if ( $null -eq  $validateCredentialsTest)
        {
            throw [System.ArgumentOutOfRangeException] "Credentials are not valid.  ('" + $credentialsOfCurrentUser.GetNetworkCredential().Domain + '\' + $credentialsOfCurrentUser.GetNetworkCredential().UserName + "')"
        }
        else
        {
            $t = $host.ui.RawUI.ForegroundColor
            $host.ui.RawUI.ForegroundColor = "Magenta"
            Write-Output "GOOD CREDENTIALS"
            $host.ui.RawUI.ForegroundColor = $t
        }
    }
    Catch
    {

        $ErrorMessage = $_.Exception.Message
        $FailedItem = $_.Exception.ItemName
        $StackTrace = $_.Exception.StackTrace

        $t = $host.ui.RawUI.ForegroundColor
        $host.ui.RawUI.ForegroundColor = "Red"

        Write-Output "Exception - $ErrorMessage"
        Write-Output "Exception - $FailedItem"
        Write-Output "Exception - $StackTrace"

        $host.ui.RawUI.ForegroundColor = $t

        throw [System.ArgumentOutOfRangeException] "Attempt to create System.DirectoryServices.DirectoryEntry failed.  Most likely reason is that credentials are not valid."
    }

}


Try
{

    HarvestCredentials

}
Catch
{
    $ErrorMessage = $_.Exception.Message
    $FailedItem = $_.Exception.ItemName
    $StackTrace = $_.Exception.StackTrace

    $t = $host.ui.RawUI.ForegroundColor
    $host.ui.RawUI.ForegroundColor = "Red"

    Write-Output "Exception - " + $ErrorMessage
    Write-Output "Exception - " + $FailedItem
    Write-Output "Exception - " + $StackTrace

    $host.ui.RawUI.ForegroundColor = $t

    Break
}
Finally
{
    $Time=Get-Date
    Write-Output "Done - " + $Time
}

і

.\TestCredentials.ps1 -preloadServiceAccountUserName "mydomain\myusername"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.