如何创建可调用内置基类的自定义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
相关产品推荐
相关产品推荐

