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()암호가 안전한 문자열을 제공하는 경우 그렇지 않다고 가정하는 것이 옳습니까?
코드 자키

ActiveDirectory모듈을 사용 하여 LDAP 쿼리를 수행하지 않는 이유는 무엇 입니까?
Kolob Canyon

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 ()를 사용하면 잘못된 암호 시도를 두 번 시도하는 것으로 보입니다-시도 횟수 임계 값을 제어 할 수 없습니다 우리 도메인에서는 낮습니다. 그래서 한 번 전화를 걸 때 두 번의 잘못된 시도를 원하지 않습니다.
코드 자키

domain \ user 또는 UPN (user @ domain) 형식을 사용하고 있습니까? 나는 이것을 복제 할 수있는 입장에 있지 않지만 다음 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 (이것은 get-credentials 섹션 일 뿐이므로 여기에 포함되지 않음)에 powergui가 설치되어 있으며 아래 코드 ( "Add-PSSnapin Quest.ActiveRoles.ADManagement"줄뿐만 아니라)에 대한 요구 사항입니다. powergui의 기능이 다른지 확실하지 않지만 아무도 나에게 말할 수 없으며 작동합니다.

"domain_name"섹션에서 자신의 도메인 이름을 대체하십시오.

#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"
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.