在Web请求中信任HTTPS站点的证书

时间:2016-02-08 13:46:20

标签: powershell ssl certificate powershell-v2.0

我想使用PowerShell 2.0测试我们的Web服务器(位于Intranet上)是否在线(1)或离线(0)来自包含它的服务器。为此我有一个脚本导航到页面并检查页面上是否有html字符串。

function Get-HeartBeat {
    $isAlive = $false

    try {
        $webclient = New-Object WebClient

        $userName = "xxx"
        $password = "xxx"
        $domain = "xxx"

        $url  = "ourUrl.com"
        $html = '<input type="submit">'

        $webclient.Credentials = New-Object System.Net.NetworkCredential($userName, $password, $domain)
        $webpage = $webclient.DownloadString($url)

        $isAlive = $webpage.Contains($html)
    } catch {
        # A WebException is thrown if the status code is anything but 200 (OK)
        Write-Host $_
        $isAlive = $false
    }

    return "$([Int32]$isAlive)"
}

不幸的是,这会返回错误:

  

异常调用&#34; DownloadString&#34;用&#34; 1&#34;参数:&#34;底层连接已关闭:无法为SSL / TLS安全通道建立信任关系。&#34;

信任我们的证书的一种方法是创建一个带有证书策略的类型,如下所示(修改this answer):

Add-Type @"
    using System.Net;
    using System.Security.Cryptography.X509Certificates;

    public class TrustOurCertsPolicy : ICertificatePolicy {
        public bool CheckValidationResult(
            ServicePoint servicePoint, X509Certificate certificate,
            WebRequest request, int certificateProblem) 
        {
            return certificate.Issuer.Equals("OUR ISSUER")
                && certificate.Subject.Contains("our application");
        }
    }
"@

[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustOurCertsPolicy

这仍然感觉有点&#34;字符串输入&#34;而不是100%安全。

这样安全吗?有没有更好的方法来创建一个接受一个证书的WebClient?我们应该信任的证书可以在cert:LocalMachine\My中找到。

1 个答案:

答案 0 :(得分:1)

处理证书错误的正确方法是将Web服务器证书的证书链(root和intermediat CA证书)导入本地证书存储区(分别作为受信任的根CA和中间CA)。如果服务器证书是自签名的,则需要将服务器证书导入为受信任的根CA.

另一个选项,取决于您实际需要检查的内容,可能是修改您的算法。例如,如果您确实只需要心跳(不验证实际请求是否返回特定结果),您只需尝试建立与端口的TCP连接:

function Get-HeartBeat {
  $url  = 'ourUrl.com'
  $port = 443

  $clnt = New-Object Net.Sockets.TcpClient
  try {
    $clnt.Connect($url, $port)
    1
  } catch {
    0
  } finally {
    $clnt.Dispose()
  }
}

在更新的Windows版本中,您可以将Test-NetConnection cmdlet用于同一目的:

function Get-HeartBeat {
  $url  = 'ourUrl.com'
  $port = 443

  [int](Test-Net-Connection -Computer $url -Port $port -InformationLevel Quiet)
}