Powershell v3 Invoke-WebRequest HTTPS错误


126

使用Powershell v3的Invoke-WebRequest和Invoke-RestMethod,我成功地使用POST方法将json文件发布到https网站。

我正在使用的命令是

 $cert=New-Object System.Security.Cryptography.X509Certificates.X509Certificate2("cert.crt")
 Invoke-WebRequest -Uri https://IPADDRESS/resource -Credential $cred -certificate $cert -Body $json -ContentType application/json -Method POST

但是,当我尝试使用GET方法时:

 Invoke-WebRequest -Uri https://IPADDRESS/resource -Credential $cred -certificate $cert -Method GET

返回以下错误

 Invoke-RestMethod : The underlying connection was closed: An unexpected error occurred on a send.
 At line:8 char:11
 + $output = Invoke-RestMethod -Uri https://IPADDRESS/resource -Credential $cred
 +           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest)      [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

我尝试使用以下代码忽略SSL证书,但不确定其是否实际起作用。

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

有人可以提供一些有关这里可能出什么问题以及如何解决的指南吗?

谢谢


那么,您正在使用哪一个?Invoke-RestMethod还是Invoke-WebRequest
svick 2012年

调用WebRequest。我使用它,因为它返回的请求/响应头与Invoke-RestMethod不同。但是我尝试了Invoke-RestMethod,它也使用相同的参数。
2012年

对于它的价值,ServerValidationCallback几乎肯定是一条红鲱鱼,因为在遇到SSL验证问题时应该得到的错误应该说:Invoke-WebRequest : The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel. 您可以尝试探索$ Error [0] .Exception.InnerException以获取更多信息。 。
Jaykul

Answers:


179

此替代方法对我有用http : //connect.microsoft.com/PowerShell/feedback/details/419466/new-webserviceproxy-needs-force-parameter-to-ignore-ssl-errors

基本上,在您的PowerShell脚本中:

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

$result = Invoke-WebRequest -Uri "https://IpAddress/resource"

9
注意,这个答案是正确的;但是,在另一个答案(stackoverflow.com/a/25163476/68432)上指出的观点也有效。如果您事先完成了“ [System.Net.ServicePointManager] :: ServerCertificateValidationCallback = {$ true}”,则该解决方案将不起作用。
Paul Suart

您需要按照下面的Arthur Strutzenberg答案添加类型条件检查,否则您会收到一条错误消息,指出类型已经存在
Ralph Willgoss

在生产中使用此产品是否存在安全风险?
Amjad

13
5年后,仍然是PowerShell 5.1(完整的.NET Framework)的解决方案。对于PowerShell Core,-SkipCertificateCheck现在有一个。
evilSnobu

MS已断开连接,该链接无效。还有其他链接吗?
Mark Heath

71

Lee的回答很好,但是我也遇到了Web服务器支持哪些协议的问题。
在还添加了以下几行之后,我可以通过https请求。如在此答案中指出的https://stackoverflow.com/a/36266735

$AllProtocols = [System.Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12'
[System.Net.ServicePointManager]::SecurityProtocol = $AllProtocols

我使用Lee的代码的完整解决方案。

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

您是否找到了更好的解决方案,因为如果您有40个脚本,则必须将其添加到每个脚本中?似乎没有任何意义。顺便说一句,感谢您的回答
Ender

1
李的回答对我没有用。我必须添加您引用的位并成功!
Pat K

非常感谢您,我们指定了有助于解决问题的协议
亚历克斯

1
谢谢谢谢您向我展示了SecurityProtocol全局静态属性。基督,我刚刚在检查证书,信任,网络,路由,权限和其他事情上花了几天的时间,试图endpoint does not respond通过https访问一台特定的服务器(所有其他方法都能正常工作),以解决模糊的错误,只是因为那个该死的powershell 5.1默认为SSL3,TLS,它只是BLOCKS该死TLS11和TLS12 默认的上帝,我是多么讨厌这个废话,我应该写了一个脚本在C#/红宝石/ C ++,或其他任何这不是PowerShell的
羽蛇

1
@StanTastic:我认为不可能永久更改默认值。我认为它已硬编码在ServicePointManager源代码中。我从没检查过,所以也许有办法。
quetzalcoatl

10

您尝试使用System.Net.WebClient吗?

$url = 'https://IPADDRESS/resource'
$wc = New-Object System.Net.WebClient
$wc.Credentials = New-Object System.Net.NetworkCredential("username","password")
$wc.DownloadString($url)

Sunny,使用该代码时收到以下消息:带有“ 1”参数的调用“ DownloadString”的异常:“远程服务器返回错误:(406)不可接受。” 在第4行:char:1 + $ wc.DownloadString($ url)+ ~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo:未指定:(:) [ ],MethodInvocationException + FullyQualifiedErrorId:WebException
floyd

基于REST服务的API文档,im使用406表示“请求中包含的accept标头不允许XML或JSON响应”
floyd 2012年

如果不允许XML / JSON响应,则允许哪些响应类型?
Sunny Chakraborty 2012年

这是您正在使用的自定义Web服务吗?REST API是否有任何公开可用的文档?
Sunny Chakraborty 2012年

这是一个称为EM7的票务系统,我认为他们没有公开文档。该服务确实接受JSON / XML响应(如果使用cURL,则可以正常工作)我相信该错误表明System.Net.WebClient不是吗?
floyd

9

纯的替代实现 (没有Add-Type 资源):

#requires -Version 5
#requires -PSEdition Desktop

class TrustAllCertsPolicy : System.Net.ICertificatePolicy {
    [bool] CheckValidationResult([System.Net.ServicePoint] $a,
                                 [System.Security.Cryptography.X509Certificates.X509Certificate] $b,
                                 [System.Net.WebRequest] $c,
                                 [int] $d) {
        return $true
    }
}
[System.Net.ServicePointManager]::CertificatePolicy = [TrustAllCertsPolicy]::new()

7

以下代码对我有用(并使用了最新的,不建议使用的方法与SSL证书/回调功能进行交互),并且没有尝试在同一powershell会话中多次加载相同的代码:

if (-not ([System.Management.Automation.PSTypeName]'ServerCertificateValidationCallback').Type)
{
$certCallback=@"
    using System;
    using System.Net;
    using System.Net.Security;
    using System.Security.Cryptography.X509Certificates;
    public class ServerCertificateValidationCallback
    {
        public static void Ignore()
        {
            if(ServicePointManager.ServerCertificateValidationCallback ==null)
            {
                ServicePointManager.ServerCertificateValidationCallback += 
                    delegate
                    (
                        Object obj, 
                        X509Certificate certificate, 
                        X509Chain chain, 
                        SslPolicyErrors errors
                    )
                    {
                        return true;
                    };
            }
        }
    }
"@
    Add-Type $certCallback
 }
[ServerCertificateValidationCallback]::Ignore();

改编自以下文章 https://d-fens.ch/2013/12/20/nobrainer-ssl-connection-error-when-using-powershell/


5

我发现当我使用此回调函数忽略SSL证书时 [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}

我总是收到错误消息Invoke-WebRequest : The underlying connection was closed: An unexpected error occurred on a send.,听起来像是您得到的结果。

我找到了这个论坛帖子,将我带到下面的功能。我在其他代码的范围内运行了一次,它对我有用。

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
}


1

我尝试搜索有关EM7 OpenSource REST API的文档。到目前为止没有运气。

http://blog.sciencelogic.com/sciencelogic-em7-the-next-generation/05/2011

关于开源REST API的讨论很多,但是没有链接到实际的API或任何文档。也许我不耐烦。

您可以尝试以下几件事

$a = Invoke-RestMethod -Uri https://IPADDRESS/resource -Credential $cred -certificate $cert 
$a.Results | ConvertFrom-Json

尝试此操作以查看是否可以过滤掉从API获取的列

$a.Results | ft

或者,您也可以尝试使用

$b = Invoke-WebRequest -Uri https://IPADDRESS/resource -Credential $cred -certificate $cert 
$b.Content | ConvertFrom-Json

卷毛样式标题

$b.Headers

我使用twitter JSON API测试了IRM / IWR。

$a = Invoke-RestMethod http://search.twitter.com/search.json?q=PowerShell 

希望这可以帮助。


感谢您的协助。但是,第一个命令$ a = Invoke-RestMethod(...)是当前不适用于我的命令。在HTTP站点上工作正常,但是当您引入HTTP7时,EM7会返回所描述的错误。这是针对Invoke-RestMethod和Invoke-WebRequest的。我正在使用Invoke-Command cmdlet并运行curl的过程中。
floyd 2012年

1

调用WebRequest“域名” -SkipCertificateCheck

您可以使用-SkipCertificateCheck Parameter作为单行命令来实现此目的(此参数仅在CORE PSEDITION上受支持)


0
  1. 运行此命令

New-SelfSignedCertificate -certstorelocation cert:\ localmachine \ my -dnsname {您的站点主机名}

在Powershell中使用管理员权限,这将在“个人”目录中生成所有证书

  1. 要摆脱“隐私”错误,请选择这些证书,右键单击→复制。并粘贴到受信任的根证书颁发机构/证书中。
  2. 最后一步是在IIS中选择正确的绑定。转到IIS网站,选择“绑定”,再选择“ SNI”复选框,然后为每个网站设置单独的证书。

确保网站主机名和证书dns-name应该完全匹配


0

这些注册表设置会影响.NET Framework 4+,从而影响PowerShell。设置它们并重新启动任何PowerShell会话以使用最新的TLS,无需重新启动。

Set-ItemProperty -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value '1' -Type DWord
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value '1' -Type DWord 

请参阅https://docs.microsoft.com/zh-cn/dotnet/framework/network-programming/tls#schusestrongcrypto


对于任何其他看到此答案的人,我们的经验是,此注册表修补程序实际上确实需要重新启动才能保证正常运行。当试图确保运行.NET应用程序的Windows框之间的TLS 1.2连接时,通过网络跟踪显示SSL 3已与该注册表值一起使用,但在重新启动之前;仅在重新引导后才调用TLS 1.2。
David W

-1

如果您以管理员身份运行此错误,该错误应消失

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.