Kiểm tra xem đầu vào mật khẩu người dùng có hợp lệ trong tập lệnh Powershell không


30

Tôi đang làm việc với tập lệnh Powershell có thêm các tác vụ theo lịch trình cho các hệ thống trong miền của chúng tôi. Khi tôi chạy tập lệnh này, nó sẽ nhắc tôi nhập mật khẩu. Đôi khi, tôi sử dụng mật khẩu và quá trình bắt đầu, khóa tài khoản của tôi. Có cách nào để xác minh thông tin đăng nhập của tôi để đảm bảo rằng những gì tôi đã nhập sẽ xác thực với Miền không?

Tôi muốn tìm một cách để truy vấn Bộ điều khiển miền. Tôi đã thực hiện một số tìm kiếm trên Google và tôi sẽ có thể thực hiện truy vấn WMI và bẫy lỗi. Tôi muốn tránh phong cách xác nhận đó nếu có thể.

Có ý kiến ​​gì không? Cảm ơn trước.

Câu trả lời:


26

Tôi có cái này trong thư viện của tôi:

$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
Nếu tôi không nhầm, điều này cuối cùng sẽ gửi mật khẩu bằng văn bản đơn giản trên mạng, phải không? Nếu đúng như vậy, thì tôi có đúng AccountManagement.PrincipalContext.ValidateCredentials()không khi cho rằng điều đó không xảy ra (nếu bạn cung cấp bảo mật cho mật khẩu)?
Code

Tại sao bạn không sử dụng ActiveDirectorymô-đun để thực hiện truy vấn LDAP của mình?
Hẻm núi Kolob

6 năm trước không có mô-đun thư mục hoạt động
Jim B

Kịch bản này cũng giúp cho các tình huống mà bạn không thể cài đặt các mô-đun AD PowerShell vì lý do này hay lý do khác.
Dodzi Dzakuma

16

Đây là những gì tôi đã sử dụng trong quá khứ; nó được cho là hoạt động cho các tài khoản máy cục bộ và 'thư mục ứng dụng', nhưng cho đến nay tôi chỉ sử dụng thành công với thông tin đăng nhập 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)
    }
}

Tôi rất muốn nghe nếu ai đó nhận thấy điều này - Tôi tin rằng khi tôi sử dụng ValidateCredentials () theo cách này với mật khẩu không chính xác, nó dường như kích hoạt hai (2) lần thử mật khẩu xấu - Tôi không thể kiểm soát số lần thử trên miền của chúng tôi và nó ở mức thấp, vì vậy tôi không muốn có hai lần thử xấu khi tôi thực hiện một cuộc gọi ... có ai có thể thấy điều này không?

Bạn đang sử dụng định dạng domain \ user hoặc UPN (user @ domain)? Tôi không ở vị trí để sao chép điều này, nhưng URL sau đây mô tả một vấn đề tương tự: social.msdn.microsoft.com/Forums/vstudio/en-US/ Lỗi
jbsmith

Bạn có thể chỉ cần chuyển $contextlàm đối số cho hàm tạo. PowerShell sẽ tự động chuyển đổi chuỗi thành enum. Tốt hơn nữa, chỉ cần làm cho [System.DirectoryServices.AccountManagement.ContextType]các loại $context. Ngoài ra, tại sao bạn sử dụng beginprocessở đây? Các đường ống có vẻ như một cách kỳ lạ để sử dụng chức năng này.
jpmc26

@ jpmc26: nhập $contexttham số [System.DirectoryServices.AccountManagement.ContextType]không phải là một tùy chọn, vì lắp ráp chứa không được tải cho đến khi thân hàm được thực thi; sử dụng đường ống là hữu ích nếu bạn muốn xác thực nhiều thông tin đăng nhập.
mkuity

@mkuity Không có lý do nào Add-Typecuộc gọi không thể được chuyển ra ngoài chức năng, trước khi định nghĩa của nó được thực thi. Tôi do dự khi có một Add-Typecuộc gọi chạy vô điều kiện bên trong chức năng ngay cả khi nó đã được tải, dù sao đi nữa. Xác thực nhiều thông tin đồng thời có vẻ như là một tình huống kỳ lạ ở nơi đầu tiên. Trong trường hợp hiếm hoi đó là những gì bạn muốn, bạn có thể dễ dàng thực hiện cuộc gọi ForEach-Object, vì vậy tôi không thấy lý do nào làm phức tạp chức năng với nó.
jpmc26

1

Tôi thấy bài đăng này hữu ích tuy nhiên nó không giải quyết được vấn đề của tôi khi tôi đang cố chạy nó từ một tập lệnh với tài khoản quản trị viên cục bộ đã đăng nhập. Nó dường như không hoạt động như một quản trị viên cục bộ (chỉ khi đăng nhập với tư cách là người dùng tên miền).

Tuy nhiên cuối cùng tôi đã xoay sở để có được một giải pháp hiệu quả và vì nó quá nhiều rắc rối nên tôi nghĩ tôi sẽ chia sẻ nó ở đây để bất kỳ ai khác có vấn đề này sẽ có câu trả lời ngay tại đây. Cả hai câu trả lời trên một trang tùy thuộc vào nhu cầu của bạn.

Lưu ý rằng cao hơn trong scipt (không bao gồm ở đây vì đây chỉ là phần thông tin xác thực) powergui được cài đặt và là một yêu cầu cho mã này bên dưới (cũng như dòng "Add-PSSnapin Quest.ActiveRoles.ADQuản lý"). Không chắc powergui có gì khác biệt nhưng không ai có thể nói với tôi và nó hoạt động.

Đăng ký tên miền của riêng bạn trong phần "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

(chưa) Phiên bản khác:

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"
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.