You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PowerShell 5.1中C#与PowerShell类证书验证回调的差异问题

解决PowerShell 5.1及更早版本中Invoke-WebRequest自签名证书验证错误

问题场景

在PowerShell 5.1或更早版本环境中,调用Invoke-WebRequest访问使用自签名证书的站点时,会抛出以下错误:

Invoke-WebRequest : The underlying connection was closed: An unexpected error occurred on a send.

测试发现一段嵌入C#代码的PowerShell脚本可解决该问题,代码如下:

$code = @"
public class SSLHandler
{
    public static System.Net.Security.RemoteCertificateValidationCallback GetSSLHandler()
    {

        return new System.Net.Security.RemoteCertificateValidationCallback((sender, certificate, chain, policyErrors) => { return true; });
    }
    
}
"@

Add-Type -TypeDefinition $code
# 关闭证书验证检查
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = [SSLHandler]::GetSSLHandler()
# 执行请求
try
{
    invoke-WebRequest -Uri myurl -UseBasicParsing
} catch {
    # 异常处理逻辑
} finally {
   # 恢复证书验证检查
   [System.Net.ServicePointManager]::ServerCertificateValidationCallback = $null
}

问题:PowerShell类改写无效

尝试将上述C#类改写为原生PowerShell类,但设置[System.Net.ServicePointManager]::ServerCertificateValidationCallback后无法生效,代码对比如下:

可正常运行的C#实现

# Works
$UnsafeWebRequest = @'
public class UnsafeWebRequest
{
    public static System.Net.Security.RemoteCertificateValidationCallback DangerousAcceptAnyServerCertificateValidator()
    {
        return new System.Net.Security.RemoteCertificateValidationCallback( (Sender, Certificate, Chain, PolicyErrors) => { return true; } );
    }   
}
'@

Add-Type -TypeDefinition $UnsafeWebRequest
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = [UnsafeWebRequest]::DangerousAcceptAnyServerCertificateValidator()

无法生效的PowerShell类实现

# Does not work
class UnsafeWebRequest 
{
    static [System.Net.Security.RemoteCertificateValidationCallback] DangerousAcceptAnyServerCertificateValidator() 
    {
        return [System.Net.Security.RemoteCertificateValidationCallback]{
            param
            (
                [System.Object] $Sender,
                [System.Security.Cryptography.X509Certificates.X509Certificate] $X509Certificate,
                [System.Security.Cryptography.X509Certificates.X509Chain] $X509Chain,
                [System.Net.Security.SslPolicyErrors] $SslPolicyErrors
            ) 
            return $True
        }
    }
}

[System.Net.ServicePointManager]::ServerCertificateValidationCallback = [UnsafeWebRequest]::DangerousAcceptAnyServerCertificateValidator()

PowerShell原生解决方案

经分析后,找到两个无需嵌入C#的PowerShell原生解决方案:

解决方案1:通过LINQ表达式编译回调函数

function New-RemoteCertificateValidationCallbackHandler
{
    [CmdletBinding()]
    [OutputType( [System.Net.Security.RemoteCertificateValidationCallback] )]
    Param ()
    Begin
    {
        Add-Type -AssemblyName System.Net
    }
    Process
    {
        $LinqLambdaExpression = [System.Linq.Expressions.Expression]::Lambda(
            [System.Net.Security.RemoteCertificateValidationCallback],
            
            [System.Linq.Expressions.Expression]::Block(
                [System.Linq.Expressions.Expression]::Constant($True)
            ),
            
            [System.Linq.Expressions.ParameterExpression[]](
                [System.Linq.Expressions.Expression]::Variable([System.Object]),
                [System.Linq.Expressions.Expression]::Variable([System.Security.Cryptography.X509Certificates.X509Certificate]),
                [System.Linq.Expressions.Expression]::Variable([System.Security.Cryptography.X509Certificates.X509Chain]),
                [System.Linq.Expressions.Expression]::Variable([System.Net.Security.SslPolicyErrors])
            )
        )
    }
    End
    {
        $LinqLambdaExpression.Compile()
    }
}

[System.Net.ServicePointManager]::ServerCertificateValidationCallback = New-RemoteCertificateValidationCallbackHandler

解决方案2:实现ICertificatePolicy接口(已过时)

注意:CertificatePolicy已被标记为过时,建议优先使用ServerCertificateValidationCallback方案

class TrustAllCertificatePolicy : System.Net.ICertificatePolicy
{
    [System.Boolean] CheckValidationResult (
        [System.Net.ServicePoint] $ServicePoint,
        [System.Security.Cryptography.X509Certificates.X509Certificate] $X509Certificate,
        [System.Net.WebRequest] $WebRequest,
        [System.Int32] $CertificateProblem
    )
    {
        return $True
    }
}

[System.Net.ServicePointManager]::CertificatePolicy = [TrustAllCertificatePolicy]::new()

内容的提问来源于stack exchange,提问作者Kjell Computer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 21:24:54