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

如何创建可调用内置基类的自定义CertificateHandler?

解决UnityWebRequest Curl Error 60的SSL证书验证问题

核心思路

不要等请求报错后再切换Handler,直接实现优先级验证的自定义CertificateHandler:先执行系统默认的证书验证逻辑,失败后自动触发自定义处理流程,从根源避免依赖错误文本判断的不可靠性。

实现步骤

1. 自定义CertificateHandler类

继承Unity的CertificateHandler,重写ValidateCertificate方法,先尝试系统级验证,失败后执行自定义逻辑:

using UnityEngine;
using UnityEngine.Networking;
using System.Security.Cryptography.X509Certificates;

public class FallbackCertificateHandler : CertificateHandler
{
    // 可选:预定义你信任的证书SHA256哈希(比完全忽略验证更安全)
    private readonly string[] _trustedCertHashes = new[]
    {
        "你的目标证书SHA256哈希值",
        "其他需要信任的证书哈希"
    };

    // 标记是否触发过自定义验证逻辑
    public bool UsedCustomValidation { get; private set; }

    protected override bool ValidateCertificate(byte[] certificateData)
    {
        bool systemValidationPassed = false;
        // 第一步:执行系统默认证书信任链验证
        try
        {
            var cert = new X509Certificate2(certificateData);
            var chain = new X509Chain();
            systemValidationPassed = chain.Build(cert);
        }
        catch
        {
            systemValidationPassed = false;
        }

        // 系统验证通过,直接返回成功
        if (systemValidationPassed)
        {
            UsedCustomValidation = false;
            return true;
        }

        // 第二步:系统验证失败,执行自定义验证逻辑
        UsedCustomValidation = true;
        return ValidateCustomCertificate(certificateData);
    }

    private bool ValidateCustomCertificate(byte[] certificateData)
    {
        // 方案1:验证证书哈希是否在信任列表内(推荐)
        string certHash = GetCertificateHashSHA256(certificateData);
        foreach (var trustedHash in _trustedCertHashes)
        {
            if (certHash.Equals(trustedHash, System.StringComparison.OrdinalIgnoreCase))
                return true;
        }

        // 方案2:完全跳过验证(仅测试环境使用,生产环境禁止)
        // return true;

        // 自定义验证也失败,返回false
        return false;
    }

    // 辅助方法:计算证书的SHA256哈希值
    private string GetCertificateHashSHA256(byte[] certificateData)
    {
        using (var sha256 = System.Security.Cryptography.SHA256.Create())
        {
            byte[] hashBytes = sha256.ComputeHash(certificateData);
            return System.BitConverter.ToString(hashBytes).Replace("-", "").ToLowerInvariant();
        }
    }
}

2. 绑定自定义Handler发起请求

创建UnityWebRequest时直接绑定该Handler,无需等报错后切换:

IEnumerator SendSecureRequest(string url)
{
    using (var request = UnityWebRequest.Get(url))
    {
        var certHandler = new FallbackCertificateHandler();
        request.certificateHandler = certHandler;

        yield return request.SendWebRequest();

        // 处理请求结果
        if (request.result == UnityWebRequest.Result.Success)
        {
            Debug.Log("请求成功:" + request.downloadHandler.text);
        }
        else
        {
            // 精准判断是否是证书验证失败
            if (request.result == UnityWebRequest.Result.ConnectionError && certHandler.UsedCustomValidation)
            {
                Debug.LogError("证书验证失败:系统信任链验证不通过,自定义验证也未通过");
            }
            else
            {
                Debug.LogError("请求失败:" + request.error);
            }
        }

        certHandler.Dispose();
    }
}

关键注意事项

  • 生产环境禁用完全跳过验证:仅在测试阶段临时使用return true跳过验证,正式上线必须采用信任特定证书哈希的方式,避免安全风险。
  • 证书哈希获取方式:通过浏览器查看目标网站证书详情,复制SHA256指纹(去掉空格、冒号等分隔符)。
  • 复用Handler实例:频繁发起请求时,可复用同一个Handler实例,减少资源开销。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 12:43:07