Powershell v3 Invoke-WebRequest HTTPS 错误

Posted

技术标签:

【中文标题】Powershell v3 Invoke-WebRequest HTTPS 错误【英文标题】:Powershell v3 Invoke-WebRequest HTTPS error 【发布时间】:2012-07-26 16:07:02 【问题描述】:

使用 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-RestMethodInvoke-WebRequest? 调用-WebRequest。我使用它,因为它返回请求/响应标头,这与 Invoke-RestMethod 不同。但是我尝试过 Invoke-RestMethod,它也采用相同的参数。 对于它的价值,ServerValidationCallback 几乎可以肯定是一个红鲱鱼,因为当你遇到 SSL 验证问题时应该得到的错误应该说:Invoke-WebRequest : The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel. 你可以尝试探索 $Error[ 0].Exception.InnerException 了解更多信息... 【参考方案1】:

这个变通办法对我有用: 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"

【讨论】:

注意,这个答案是正确的;但是,关于另一个答案(***.com/a/25163476/68432)的观点也是有效的。如果您事先已完成“[System.Net.ServicePointManager]::ServerCertificateValidationCallback = $true”,则此解决方案将不起作用。 您需要根据下面的 Arthur Strutzenberg 回答添加类型条件检查,否则您将收到错误提示该类型已存在 在生产中使用它是否存在安全风险? 5 年后,这仍然是 PowerShell 5.1(完整的 .NET Framework)的解决方案。对于 PowerShell Core,现在有一个 -SkipCertificateCheck @Amjad 在生产中使用它确实存在安全风险 - 如果有人将您的呼叫重定向到恶意替代端点(可能就像在调用它的机器上编辑主机文件一样简单),那么您的呼叫无论将所有信息发送给攻击者,都会进行【参考方案2】:

Lee 的回答很好,但我也遇到了 Web 服务器支持的协议的问题。 在还添加以下行之后,我可以通过 https 请求。正如这个答案中指出的https://***.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 个脚本,那么您必须将其添加到每个脚本中?似乎没有任何意义。顺便说一句,谢谢你的回答 李的回答对我不起作用。我必须添加你引用的位并且它工作了! 谢谢谢谢谢谢你给我看SecurityProtocol全局静态属性。天哪,我刚刚在检查证书、信任、网络、路由、权限和其他东西上浪费了几天时间,试图在通过 https 访问一台特定服务器时解决模糊的endpoint does not respond 错误(所有其他都可以),只是因为那该死的 powershell 5.1 默认为 SSL3,TLS,它只是 BLOCKS GODDAMN TLS11 和 TLS12 BY DEFAULT 天哪,我多么讨厌这个废话,我应该用 C#/Ruby/ 编写那个脚本C++,或者其他不是 powershell 的东西 @quetzalcoatl,如何更改默认值?你和 AndOs 帮了我很多,这就足够了: $AllProtocols = [System.Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12' 然后 [System.Net.ServicePointManager]::SecurityProtocol = $AllProtocols @StanTastic:我认为永久更改默认值是不可能的。我认为它在 ServicePointManager 源代码中是硬编码的。不过我从来没有检查过,所以也许有什么办法。【参考方案3】:

纯powershell 的替代实现(没有Add-Type 的c# 源):

#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()

【讨论】:

【参考方案4】:

您是否尝试过使用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)不可接受。”在 line:4 char:1 + $wc.DownloadString($url) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [ ], MethodInvocationException + FullyQualifiedErrorId : WebException 基于 REST 服务的 API 文档,im using 406 表示“请求中包含的接受标头不允许 XML 或 JSON 响应” 如果不允许 XML / JSON 响应,则允许哪些响应类型? 这是您正在使用的自定义 Web 服务吗? REST API 是否有任何公开可用的文档? 这是一个名为 EM7 的票务系统,我不相信他们有公共文档。该服务确实接受 JSON/XML 响应(如果我使用 cURL 就可以正常工作)我相信错误表明 System.Net.WebClient 不是?【参考方案5】:

Invoke-WebRequest "DomainName" -SkipCertificateCheck

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

【讨论】:

这个参数救了我。我在 Azure 中使用了 invoke-WebRequest,它不支持“Add-Type”,只有这个可以工作。非常感谢!【参考方案6】:

以下工作对我有用(并使用最新的非弃用方式与 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/

【讨论】:

【参考方案7】:

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

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

我发现了这个forum post,它引导我进入下面的函数。我在其他代码的范围内运行了一次,它对我有用。

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

【讨论】:

【参考方案8】:

我尝试搜索有关 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 站点,但是当您引入 EM7 的 HTTPS 时,它会返回所描述的错误。这适用于 Invoke-RestMethod 和 Invoke-WebRequest。我正在使用 Invoke-Command cmdlet 并运行 curl。【参考方案9】:

这些注册表设置会影响 .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/en-us/dotnet/framework/network-programming/tls#schusestrongcrypto

【讨论】:

对于看到此答案的其他人,我们的经验是,此注册表补丁实际上确实需要重新启动才能保证正常运行。当试图确保运行 .NET 应用程序的 Windows 机器之间的 TLS 1.2 连接时,通过网络跟踪显示 SSL 3 与此注册表值一起使用,但在重新启动之前;仅在重新启动后才调用 TLS 1.2。【参考方案10】:
    运行此命令

New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname your-site-hostname

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

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

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

【讨论】:

【参考方案11】:

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

【讨论】:

以上是关于Powershell v3 Invoke-WebRequest HTTPS 错误的主要内容,如果未能解决你的问题,请参考以下文章

powershell 使用REST-API的PowerShell V3 Multipart / formdata示例(Invoke-RestMethod)

Powershell v3.0 管道问题

powershell 迁移Web应用程序中所有Web的SharePoint UI(v3到v4)。

Powershell v3 Invoke-WebRequest HTTPS 错误

PowerShell - 启动进程和命令行开关

什么是Powershell?