.NET 4.6.1通过SSL连接Redis失败,同服务器Java(Jedis)可连接
问题概述
同一Windows服务器上,.NET 4.6.1程序使用StackExchange.Redis通过SSL连接Redis时抛出认证失败错误,而使用相同证书和密码的Java Jedis代码可正常连接,报错信息如下:
It was not possible to connect to the redis server(s). There was an authentication failure; check that passwords (or client certificates) are configured correctly: (IOException) Authentication failed because the remote party has closed the transport stream..
at StackExchange.Redis.ConnectionMultiplexer.ConnectImpl(ConfigurationOptions configuration, TextWriter log, Nullable`1 serverType, EndPointCollection endpoints)
核心修复方案
对比Java与.NET代码的差异,问题集中在客户端证书权限、证书链验证逻辑、SSL协议配置三个维度,以下是针对性修复步骤:
1. 修复客户端证书加载权限
Windows环境下直接加载PFX证书可能因私钥访问权限不足导致证书无法正常发送,需添加X509KeyStorageFlags参数:
options.CertificateSelection += delegate { Console.WriteLine("Fectching certificate to send to redis"); var cert = new X509Certificate2(PATH_TO_CERT_FILE, "password", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable); return cert; };
2. 修正服务器证书验证逻辑
原验证函数仅简单对比颁发者与根证书主题,未完成完整证书链验证,调整为:
private static bool Options_CertificateValidation(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { // 无SSL错误直接通过 if (sslPolicyErrors == SslPolicyErrors.None) return true; // 加载根证书并加入验证链信任列表 X509Certificate2 rootCert = new X509Certificate2("C:\\serverCert.pem"); chain.ChainPolicy.ExtraStore.Add(rootCert); // 测试环境临时禁用吊销检查(生产环境建议开启) chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; // 验证证书链完整性+颁发者匹配 bool isChainValid = chain.Build(new X509Certificate2(certificate)); bool isIssuerMatch = certificate.Issuer.Equals(rootCert.Subject, StringComparison.OrdinalIgnoreCase); return isChainValid && isIssuerMatch; }
3. 显式指定SSL协议版本
尽管.NET 4.6.1默认支持TLS 1.2,显式指定可避免协商兼容问题:
var options = ConfigurationOptions.Parse(configString); options.SslProtocols = SslProtocols.Tls12;
4. 优化密码配置方式
避免连接字符串拼接密码导致的特殊字符转义问题,改用属性设置:
// 移除连接字符串中的password={pass} var configString = $"{host}:{port},ssl=true"; var options = ConfigurationOptions.Parse(configString); options.Password = pass;
5. 启用日志排查细节
若问题仍存在,开启日志获取连接过程详情:
var logWriter = new StringWriter(); ConnectionMultiplexer muxer = ConnectionMultiplexer.Connect(options, logWriter); Console.WriteLine("Redis连接日志:"); Console.WriteLine(logWriter.ToString());
内容的提问来源于stack exchange,提问作者jagadeesh

