Powershell 3.0 Invoke-WebRequest HTTPS所有请求都失败



我正试图通过Powershell 3.0和REST API与我们的负载均衡器一起工作。然而,我目前得到的失败无论我尝试,如果它是一个https请求,无论是我们的负载均衡器或任何其他https网站。我觉得我错过了一些明显的东西。

下面是使用https 失败的代码
try
{
    #fails
    #$location='https://www.bing.com'
    #fails
    #$location='https://www.google.com'
    #fails
    #$location='https://www.facebook.com'
    #fails
    #$location='https://www.ebay.com'
    #works
    #$location='http://www.bing.com'
    #works
    #$location='http://www.google.com'
    #fails (looks like Facebook does a redirect to https://)
    $location='http://www.facebook.com'
    #works
    #$location='http://www.ebay.com'
    $response=''
    $response = Invoke-WebRequest -URI $location
    $response.StatusCode
    $response.Headers
}
catch
{
    Write-Host StatusCode $response.StatusCode
    Write-Host $_.Exception
}
我得到的错误是:
System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a send. ---> System.Management.Automation.PSInvalidOperationException: 
There is no Runspace available to run scripts in this thread. You can provide one in the DefaultRunspace property of the System.Management.Automation.Runspaces.Runspa
ce type. The script block you attempted to invoke was: $true
   at System.Net.TlsStream.EndWrite(IAsyncResult asyncResult)
   at System.Net.ConnectStream.WriteHeadersCallback(IAsyncResult ar)
   --- End of inner exception stack trace ---
   at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.GetResponse(WebRequest request)
   at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.ProcessRecord()

我希望这一页和底部的建议(包括Aaron D.的建议)会有所不同,但没有一个有所不同。

[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}

function Ignore-SSLCertificates
{
    $Provider = New-Object Microsoft.CSharp.CSharpCodeProvider
    $Compiler = $Provider.CreateCompiler()
    $Params = New-Object System.CodeDom.Compiler.CompilerParameters
    $Params.GenerateExecutable = $false
    $Params.GenerateInMemory = $true
    $Params.IncludeDebugInformation = $false
    $Params.ReferencedAssemblies.Add("System.DLL") > $null
    $TASource=@'
    namespace Local.ToolkitExtensions.Net.CertificatePolicy
    {
        public class TrustAll : System.Net.ICertificatePolicy
        {
            public bool CheckValidationResult(System.Net.ServicePoint sp,System.Security.Cryptography.X509Certificates.X509Certificate cert, System.Net.WebRequest req, int problem)
            {
                return true;
            }
        }
    }
'@ 
    $TAResults=$Provider.CompileAssemblyFromSource($Params,$TASource)
    $TAAssembly=$TAResults.CompiledAssembly
    ## We create an instance of TrustAll and attach it to the ServicePointManager
    $TrustAll = $TAAssembly.CreateInstance("Local.ToolkitExtensions.Net.CertificatePolicy.TrustAll")
    [System.Net.ServicePointManager]::CertificatePolicy = $TrustAll
}

add-type @"
    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;
        }
    }
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy

我已经尝试切换到调用- restcommand,但无济于事,因为我得到相同的响应。

感觉这必须是环境的东西,因为我不能相信上面的不适合任何人,但我已经在工作站和服务器上尝试了相同的结果(不完全排除环境,但我知道它们的设置不同)。

任何想法吗?

这对我来说非常有效。网站默认使用TLS 1.0,显然PS不支持。我用了这一行:

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

我的PS脚本(到目前为止我测试过的所有脚本)都工作得很好。

答案是不要这样做来解决SSL问题:

[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}

如果你这样做,你的第一个https请求将工作(看起来),但随后的不会。此外,此时您需要关闭Powershell ISE,并重新打开它,然后再试一次(没有该行)。

这是暗示在这里的一句话http://social.technet.microsoft.com/Forums/windowsserver/en-US/79958c6e-4763-4bd7-8b23-2c8dc5457131/sample-code-required-for-invokerestmethod-using-https-and-basic-authorisation?forum=winserverpowershell - "和所有后续运行产生这个错误:",但它不清楚重置的解决方案是什么。

我也被这个问题困扰了很长时间。它甚至影响了Visual Studio,因为VS在运行NuGet restore时将我的$PROFILE加载到它的域中。

看到你上面的评论让我意识到我有一个自定义回调脚本,因为我们的一个供应商发货的产品在其ssl证书中带有无效的CN。

长话短说,我用一个编译的c#对象替换了我的脚本委托(从方程中删除了脚本运行空间)。

(单独的代码块用于c#高亮显示)

using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
public static class CustomCertificateValidationCallback {
    public static void Install() 
    {
        ServicePointManager.ServerCertificateValidationCallback += CustomCertificateValidationCallback.CheckValidationResult;
    }
    public static bool CheckValidationResult(
        object sender, 
        X509Certificate certificate, 
        X509Chain chain, 
        SslPolicyErrors sslPolicyErrors)
    {
        // please don't do this. do some real validation with explicit exceptions.
        return true;
    }
}
在Powershell:

Add-Type "" # C# Code
[CustomCertificateValidationCallback]::Install()

巩固和浓缩了上面的一些学习,我采用了以下方法:

语法像以前的c#一样有颜色和注释:

// Piggyback in System.Net namespace to avoid using statement(s)
namespace System.Net 
{
    // Static class to make the ps call easy
    // Uses a short name that is unlikely to clash with real stuff...YMMV
    public static class Util 
    {
        // Static method for a static class
        public static void Init() 
        {
            // [optionally] clear any cruft loaded into this static scope
            ServicePointManager.ServerCertificateValidationCallback = null;
            // Append a dangerously permissive validation callback
            // using lambda syntax for brevity.
            ServicePointManager.ServerCertificateValidationCallback += 
                (sender, cert, chain, errs) => true;
            // Tell SPM to try protocols that have a chance 
            // of working against modern servers.
            // Word on the street is that these will be tried from "most secure" 
            // to least secure. Some people add em all!
            ServicePointManager.SecurityProtocol = 
                SecurityProtocolType.Tls | 
                SecurityProtocolType.Tls11 | 
                SecurityProtocolType.Tls12;
        }
    }
}

现在是真正的powershell高亮版本(没有注释,但代码相同)

Add-Type -Language CSharp @"
namespace System.Net {
public static class Util {
public static void Init() {
ServicePointManager.ServerCertificateValidationCallback = null;
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, errs) => true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
}}}"@
[System.Net.Util]::Init()

显然,您可以删除无关的空白,但您应该能够将其放入会话中,然后随意添加Invoke-WebRequest

注意

# Do not use IMHO!
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}

方法在ps 5.1中似乎很不正确(我已经测试过了)。我不知道这句话是从哪里来的,但我希望我能避免它,避免心痛。

下面的powershell脚本为我检查post web请求

add-type @"
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;
    }
}
"@
$AllProtocols = [System.Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12'
[System.Net.ServicePointManager]::SecurityProtocol = $AllProtocols
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
$uri = "XXXX"
$person = @{grant_type= 'user_password'
username = 'XXXX'
password = 'XXX'
}
   $body = (ConvertTo-Json $person)
   $hdrs = @{}
   $hdrs.Add("XXXX","XXXX")

Invoke-RestMethod -Uri $uri -Method Post -Body $body -ContentType 'application/json' -Headers $hdrs

最新更新