Powershell betiğinde kullanıcı şifresi girişinin geçerli olup olmadığını kontrol edin


30

Alanımızdaki sistemlere zamanlanmış görevler ekleyen bir Powershell betiği ile çalışıyorum. Bu betiği çalıştırdığımda, şifrem istenecek. Bazen şifreyi yağladım ve hesabımı kilitleyen işlem başladı. Yazdıklarımın Etki Alanı ile doğrulandığından emin olmak için kimlik bilgilerimi doğrulamanın bir yolu var mı?

Etki alanı denetleyicisini sorgulamanın bir yolunu bulmak istiyorum. Bazı Google aramaları yaptım ve bir WMI sorgusu yapabilmeli ve bir hata için tuzağa düşebilmeliyim. Mümkünse bu doğrulama tarzından kaçınmak istiyorum.

Herhangi bir fikir? Şimdiden teşekkürler.

Yanıtlar:


26

Kütüphanemde bu var:

$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
Yanılmıyorsam, bu parola ağ üzerinden düz metin olarak gönderilecek, değil mi? Eğer öyleyse, o zaman ben de AccountManagement.PrincipalContext.ValidateCredentials()öyle olmadığını varsaymakta haklıyım (şifre için bir güvenlik teminatı sağlarsanız)?
Code Jokey

ActiveDirectoryLDAP sorgunuzu yapmak için neden modülü kullanmıyorsunuz ?
Kolob Kanyonu

6 yıl önce aktif dizin modülü yoktu
Jim B

Bu komut ayrıca, AD PowerShell modüllerini bir nedenden ötürü kuramayacağınız durumlar için de yardımcı olur.
Dodzi Dzakuma

16

Geçmişte kullandığım şey bu; yerel makine hesapları ve 'uygulama dizini' için çalışması gerekiyordu, ancak şimdiye kadar yalnızca AD kimlik bilgileriyle başarıyla kullandım:

    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)
    }
}

Birisi bunu fark ederse duymayı çok isterim - ValidateCredentials () yöntemini yanlış bir şifre ile kullandığımda, iki (2) hatalı şifre girişimini tetikliyor gibi göründüğüne inanıyorum - Denemelerin sayısını kontrol edemiyorum etki alanımızda ve düşük, bu yüzden tek bir arama yaparken iki kötü girişimde bulunmamayı tercih ederim ... kimse bunu görebilir mi?
Code Jokey

Domain \ user veya UPN (user @ domain) formatını kullanıyor musunuz? Bunu çoğaltma pozisyonunda değilim, ancak aşağıdaki URL benzer bir sorunu anlatıyor: social.msdn.microsoft.com/Forums/vstudio/en-US/…
jbsmith

Yapıcıya $contextargüman olarak geçebilmelisiniz . PowerShell, dizeleri otomatik olarak bir numaralandırmaya dönüştürür. Daha da iyisi, sadece [System.DirectoryServices.AccountManagement.ContextType]türünü yapın $context. Ayrıca, neden burada beginve processburada kullanıyorsunuz ? Boru hattı bu işlevi kullanmak için garip bir yol gibi görünüyor.
jpmc26

@ jpmc26: yazarak $contextparametre [System.DirectoryServices.AccountManagement.ContextType]işlevi kadar düzeneği içeren yüklü değildir, çünkü bir seçenek değildir, vücut yürütülür; Birden fazla kimlik bilgilerini doğrulamak istiyorsanız, boru hattını kullanmak yardımcı olacaktır.
mklement

@mklement Çağrının Add-Type, tanımlamanın yürütülmesinden önceki işlevine dışında taşınamaması için hiçbir neden yoktur . Add-TypeZaten yüklü olsa bile, işlev içinde koşulsuz olarak art arda çalışan bir çağrı yapmakta tereddüt ediyorum . Aynı anda birden fazla kimlik bilgisini doğrulamak, ilk etapta garip bir durum gibi görünüyor. İstediğiniz bu nadir bir durumda, çağrıyı kolayca sarabilirsiniz ForEach-Object, bu yüzden işlevi onunla karmaşıklaştırmak için bir neden göremiyorum.
jpmc26

1

Bu yazıyı faydalı buldum ancak yerel yönetici hesabıyla oturum açtığımda bir komut dosyasından çalıştırmaya çalışırken sorunumu çözmedi. Yerel yönetici olarak çalışmıyor gibi görünüyor (yalnızca bir etki alanı kullanıcısı olarak oturum açıldığında).

Ancak nihayet çalışan bir çözüm bulmayı başardım ve çok fazla sorun olduğu için, bunu burada paylaşacağımı düşündüm, böylece bu problemi olan herkes tam burada cevabını alabilecekti. İhtiyaçlarınıza bağlı olarak bir sayfada iki cevap.

Notta daha yükseğe çıkıldığını (buraya sadece kimlik bilgileri bölümü olarak dahil değildir) powergui'nin yüklendiğini ve aşağıdaki kodun ("Add-PSSnapin Quest.ActiveRoles.ADManagement" satırının yanı sıra) gerekli olduğunu unutmayın. Hangi powergui'nin farklı olduğunu bilmiyorum ama başkası bana söyleyemedi ve işe yaramadı.

"Domain_name" bölümlerinde kendi alan adınızı girin.

#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

(henüz) Başka bir sürüm:

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
}

ve

.\TestCredentials.ps1 -preloadServiceAccountUserName "mydomain\myusername"
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.