【问题标题】:Trusting certificate of HTTPS site in web requestWeb 请求中 HTTPS 站点的信任证书
【发布时间】:2016-02-08 22:24:50
【问题描述】:

我想使用 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)"
}

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

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

信任我们证书的一种方法是创建一个具有如下证书策略的类型(修改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

这仍然感觉有点“字符串类型”而不是 100% 安全。

这样安全吗?有没有更好的方法来创建一个接受一个证书的 WebClient?我们应该信任的证书位于cert:LocalMachine\My

【问题讨论】:

    标签: powershell ssl certificate powershell-2.0


    【解决方案1】:

    处理证书错误的正确方法是将网络服务器证书的证书链(根证书和中间 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)
    }
    

    【讨论】:

    • 谢谢。这确实不是真正的心跳,我想确保页面得到实际服务。 ls cert:\LocalMachine\My 返回所有证书(根证书和中间证书)。我还需要把它们放在其他地方吗?
    • 它们需要分别位于 cert:\LocalMachine\Root(根 CA)和 cert:\LocalMachine\CA(中间 CA)中。
    • 好的,我们的证书不在cert:\LocalMachine\CA 中。我使用this code通过PowerShell将LocalMachine\My复制到CA。它现在有效,感觉很安全。非常感谢。
    猜你喜欢
    • 2021-11-10
    • 2016-06-07
    • 1970-01-01
    • 2014-10-12
    • 2013-10-24
    • 1970-01-01
    • 1970-01-01
    • 2011-09-01
    相关资源
    最近更新 更多