2017-08-11 51 views
2

我希望能够使用Troy Hunt's have i been pwned service提供的Pwned Passwords列表。该服务在他的Introducing 306 Million Freely Downloadable Pwned Passwords博客文章中有描述。该API使用HTTP Not Found 404状态代码来指示何时在列表中找不到密码,并使用200来指示它已在受损列表中找到。这使得通过Invoke-WebRequest PowerShell Cmdlet难以消耗,这引发了404的WebException。如何从PowerShell中检查密码与haveibeenpwned Pwned密码

我将回答这个问题,以供将来参考,并附带一些示例代码,它不需要捕获异常。

+0

大问题和答案您可以测试打开了该功能,但为什么具体你想不只是捕获异常? –

+0

对于.NET API的好奇心,当测试两个结果时,其中一个并不觉得它应该是'特殊的'@MarkWragg –

回答

4

较新的HttpClient允许您在较低级别发出Http请求,并检查HttpStatusCode而不处理404的异常,如下所示。

function Test-CompromisedPassword { 
    param([Parameter(Mandatory=$True)][string]$password) 

    # Force assembly to be loaded 
    Add-Type -AssemblyName 'System.Net.Http'  
    # By default PowerShell would use TLS 1.0 which is not supported by the API 
    [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 

    $baseUrl = "https://haveibeenpwned.com/api/v2/pwnedpassword/{0}?originalPasswordIsAHash={1}" 
    $url = $baseUrl -f $password,'false' 

    $httpClient = New-Object System.Net.Http.HttpClient 
    # User-Agent header must be set to call the API 
    $httpClient.DefaultRequestHeaders.Add("User-Agent", "PowerShell script $($MyInvocation.MyCommand.Name)") 

    # HttpClient is only Async so use .Result to force the synchronous call 
    $response = $httpClient.GetAsync($url).Result 

    Write-Verbose "$password $([int]$response.StatusCode) $($response.StatusCode)" 

    switch ([int]$response.StatusCode) { 
     200 { $passwordFound = $true; break; } 
     404 { $passwordFound = $false; break; } 
     429 { throw "Rate limit exceeded" } 
     default { throw "Not expected" + $response.StatusCode } 
    } 

    if ($response) { $response.Dispose() } 
    if ($httpClient) { $httpClient.Dispose() } 

    return $passwordFound 
} 

如下

Test-CompromisedPassword 'password' # Returns true to indicate password found 
Start-Sleep -Milliseconds 1500 # Wait for the Rate limit time to expire 
Test-CompromisedPassword ([Guid]::NewGuid()) # Returns false to indicate password not found