从Powershell Invoke-RestMethod忽略自签名证书不起作用(它再次更改......)

pet*_*snd 6 rest powershell ssl windows-10 windows-server-2016

使用标准解决方案忽略证书验证后,Invoke-RestMethod返回:

Invoke-RestMethod : A system error occurred and has been logged.  Please try again later or contact your administrator.
Run Code Online (Sandbox Code Playgroud)

我今天刚刚注意到这个失败,所以我认为它与Powershell更新有关.通过"标准解决方案"我的意思是:

[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }
Run Code Online (Sandbox Code Playgroud)

几个月前停止工作,并在C#类型中正确设置回调添加到Powershell(历史记录中的描述).

这是我的环境:

> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      5.1.15063.674
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.15063.674
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
Run Code Online (Sandbox Code Playgroud)

这是一个小历史,所以这个问题不仅仅是一个副本关闭.

历史

如果你谷歌或搜索StackOverflow你可以找到这个问题提出一些预制的回应.但是,今天我注意到所有的标准解决方案都不再适用了.

Powershell给出的标准错误是:

Invoke-RestMethod : The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.
Run Code Online (Sandbox Code Playgroud)

在所有论坛上给出的标准答案是在你打电话之前使用这个命令Invoke-RestMethod:

[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }
Run Code Online (Sandbox Code Playgroud)

但是,如果您使用的是最新版本的Windows 10/2016和Powershell,那么您的回拨Invoke-RestMethod将会返回:

Invoke-RestMethod : The underlying connection was closed: An unexpected error occurred on a send.
Run Code Online (Sandbox Code Playgroud)

为什么会发生这种情况的解释可以在Huddled Masses博客上找到.它可以概括为:

将ServerCertificateValidationCallback设置为scriptblock将不适用于异步回调(在任务线程上发生的回调),因为另一个线程将没有运行空间来执行脚本.

最初,我用这段代码解决了这个问题:

if (-not ([System.Management.Automation.PSTypeName]"TrustAllCertsPolicy").Type)
{
    Add-Type -TypeDefinition  @"
using System.Net;
using System.Security.Cryptography.X509Certificates;
public class TrustAllCertsPolicy : ICertificatePolicy {
    public bool CheckValidationResult(
        ServicePoint srvPoint, X509Certificate certificate,
        WebRequest request, int certificateProblem)
    {
        return true;
    }
}
"@
}

if ([System.Net.ServicePointManager]::CertificatePolicy.ToString() -ne "TrustAllCertsPolicy")
{
    [System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
}
Run Code Online (Sandbox Code Playgroud)

但是,这在Windows Server 2016上不起作用,即使它在Windows 10上工作正常.因此,基于Huddled Masses,我编写了这个来处理C#中的证书验证回调而不是脚本块:

function Disable-SslVerification
{
    if (-not ([System.Management.Automation.PSTypeName]"TrustEverything").Type)
    {
        Add-Type -TypeDefinition  @"
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
public static class TrustEverything
{
    private static bool ValidationCallback(object sender, X509Certificate certificate, X509Chain chain,
        SslPolicyErrors sslPolicyErrors) { return true; }
    public static void SetCallback() { System.Net.ServicePointManager.ServerCertificateValidationCallback = ValidationCallback; }
    public static void UnsetCallback() { System.Net.ServicePointManager.ServerCertificateValidationCallback = null; }
}
"@
    }
    [TrustEverything]::SetCallback()
}
function Enable-SslVerification
{
    if (([System.Management.Automation.PSTypeName]"TrustEverything").Type)
    {
        [TrustEverything]::UnsetCallback()
    }
}
Run Code Online (Sandbox Code Playgroud)

这在很长一段时间内都运行良好,但就在最近,当我打电话时,我开始收到以下错误Invoke-RestMethod:

Invoke-RestMethod : A system error occurred and has been logged.  Please try again later or contact your administrator.
Run Code Online (Sandbox Code Playgroud)

我知道一个合适的解决方案只是部署证书,但通常你只是想测试一下而不必设置适当的PKIX.

pet*_*snd 5

我想我已经将范围缩小到我正在调用的 Web 服务中的更改。哦!

我在问题中列出的Disable-SslVerificationEnable-SslVerification函数仍然是最好的方法并且似乎有效。

期待-SkipCertificateCheckBacon Bits 在评论中提到的switch。然后,我们可以停止黑客攻击。=)

希望这个问题对于那些试图解决同样问题但遇到问题的人来说是有价值的An unexpected error occurred on a send