.NET 4.7.2使用RedisSessionStateProvider双向TLS认证超时求助
我是相关技术的新手,目前在.NET Framework 4.7.2环境下,使用RedisSessionStateProvider结合TLS双向认证连接Redis时遇到以下超时错误:
Server Error in '/' Application.
Timeout performing EVAL (6000ms), inst: 0, qu: 1, qs: 0, aw: False, bw: SpinningDown,
serverEndpoint: serverName:6379, mc: 1/1/0, mgr: 10 of 10 available,
clientName: SessionStateProvider, IOCP:
(Busy=0,Free=1000,Min=2,Max=1000), WORKER:
(Busy=1,Free=32766,Min=2,Max=32767), v: 2.6.48.48654
Description: An unhandled exception occurred during the execution of
the current web request. Please review the stack trace for more
information about the error and where it originated in the code.Exception Details: StackExchange.Redis.RedisTimeoutException: Timeout
performing EVAL (6000ms), inst: 0, qu: 1, qs: 0, aw: False, bw:
SpinningDown, serverEndpoint: serverName:6379, mc: 1/1/0, mgr: 10 of
10 available, clientName: SessoinStateProvider, IOCP:
(Busy=0,Free=1000,Min=2,Max=1000), WORKER:
(Busy=1,Free=32766,Min=2,Max=32767), v: 2.6.48.48654Source Error: An unhandled exception was generated during the
execution of the current web request. Information regarding the origin
and location of the exception can be identified using the exception
stack trace below.Stack Trace:
[RedisTimeoutException: Timeout performing EVAL (6000ms), inst: 0, qu:
1, qs: 0, aw: False, bw: SpinningDown, serverEndpoint:
serverName:6379, mc: 1/1/0, mgr: 10 of 10 available, clientName:
SessionStateProvider, IOCP: (Busy=0,Free=1000,Min=2,Max=1000), WORKER:
(Busy=1,Free=32766,Min=2,Max=32767), v: 2.6.48.48654]
StackExchange.Redis.ConnectionMultiplexer.ExecuteSyncImpl(Message
message, ResultProcessor1 processor, ServerEndPoint server, T defaultValue) in /_/src/StackExchange.Redis/ConnectionMultiplexer.cs:1854 StackExchange.Redis.RedisDatabase.ScriptEvaluate(String script, RedisKey[] keys, RedisValue[] values, CommandFlags flags) in /_/src/StackExchange.Redis/RedisDatabase.cs:1501 Microsoft.Web.Redis.<>c__DisplayClass7_0.<Eval>b__0() in C:\TeamCity\buildAgent\work\59b31e8e4035fd30\src\Shared\StackExchangeClientConnection.cs:68 Microsoft.Web.Redis.StackExchangeClientConnection.OperationExecutor(Func1
redisOperation) in
C:\TeamCity\buildAgent\work\59b31e8e4035fd30\src\Shared\StackExchangeClientConnection.cs:95
Microsoft.Web.Redis.StackExchangeClientConnection.RetryLogic(Func`1
redisOperation) in
C:\TeamCity\buildAgent\work\59b31e8e4035fd30\src\Shared\StackExchangeClientConnection.cs:122
Microsoft.Web.Redis.StackExchangeClientConnection.Eval(String script,
String[] keyArgs, Object[] valueArgs) in
C:\TeamCity\buildAgent\work\59b31e8e4035fd30\src\Shared\StackExchangeClientConnection.cs:68
Microsoft.Web.Redis.RedisConnectionWrapper.Set(ISessionStateItemCollection
data, Int32 sessionTimeout) in
C:\TeamCity\buildAgent\work\59b31e8e4035fd30\src\RedisSessionStateProvider\RedisConnectionWrapper.cs:137
Microsoft.Web.Redis.d__25.MoveNext()
in
C:\TeamCity\buildAgent\work\59b31e8e4035fd30\src\RedisSessionStateProvider\RedisSessionStateProvider.cs:433
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task) +62
Microsoft.AspNet.SessionState.d__80.MoveNext()
+812
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task) +62
Microsoft.AspNet.SessionState.d__82.MoveNext() +323
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task) +62
Microsoft.AspNet.SessionState.TaskAsyncHelper.EndTask(IAsyncResult ar)
+58
System.Web.AsyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
+417
System.Web.HttpApplication.ExecuteStepImpl(IExecutionStep step) +75
System.Web.HttpApplication.ExecuteStep(IExecutionStep
step, Boolean& completedSynchronously) +158
相关配置与代码
Web.config
<add settingsClassName="RedisConfig" settingsMethodName="GetConnectionString" name="MySessionStateStore" type="Microsoft.Web.Redis.RedisSessionStateProvider" ssl="true" accessKey="somelengthypassword"/>
RedisConfig.cs
static RedisConfig() { try { var options = new ConfigurationOptions { EndPoints = { "serverName:6379" }, ClientName = "SessionStateProvider", User = "acl-username", Password = "somelengthypassword", Ssl = true, // SslProtocols = SslProtocols.Tls12, AllowAdmin = true, AbortOnConnectFail = false, ConnectTimeout = 10000, SyncTimeout = 6000, ConnectRetry = 3, CheckCertificateRevocation = false }; options.CertificateSelection += delegate { var certificate = new X509Certificate2("C:\\temp\\myclientcert.pfx", "test"); return certificate; }; conn = ConnectionMultiplexer.Connect(options); } catch (Exception) { throw; } } public static string GetConnectionString() { var config = conn.Configuration; return conn.Configuration; }
页面代码
Index.aspx
protected void GreetButton_Click(object sender, EventArgs e) { string name = NameTextBox.Text; Session.Add("MyName", name); Session.Add("SessionTime", DateTime.Now); Response.Redirect("~/Result.aspx"); }
Result.aspx
public partial class Result : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { object name = Session["MyName"]; object time = Session["SessionTime"]; if (name != null && time != null) NameLabel.Text = "Hi! " + (string)name + ", your last session state storing time was: " + time; } }
请问我哪里配置或使用出错了?
你的配置存在几个关键问题,导致双向TLS认证失败进而引发超时:
RedisSessionStateProvider配置冲突
Web.config中同时设置了settingsClassName/settingsMethodName和ssl/accessKey属性,会导致Provider逻辑冲突:代码中构建的ConnectionMultiplexer本应被优先使用,但Web.config的ssl和accessKey会干扰认证流程。需移除Web.config中的ssl和accessKey属性,避免重复配置。双向TLS证书处理方式错误
通过ConfigurationOptions.CertificateSelection事件注册客户端证书的方式,无法被RedisSessionStateProvider正确复用。因为Provider会基于返回的连接字符串重新创建连接,而事件注册的证书信息不会被序列化到连接字符串中,导致新连接缺少证书配置。
正确做法是直接使用ClientCertificate属性设置证书:
var options = new ConfigurationOptions { // 其他配置保留 Ssl = true, SslProtocols = SslProtocols.Tls12, ClientCertificate = new X509Certificate2("C:\\temp\\myclientcert.pfx", "test") };
连接字符串返回逻辑无效
GetConnectionString()返回conn.Configuration,但该字符串不包含运行时配置的证书信息,Provider拿到后无法建立双向认证连接,最终导致超时。TLS版本未显式指定
注释掉SslProtocols = SslProtocols.Tls12可能导致客户端与Redis服务器的TLS版本协商失败,需显式指定符合服务器要求的TLS版本(如TLS1.2或TLS1.3)。
修复步骤
- 修改Web.config,移除冗余属性:
<add settingsClassName="RedisConfig" settingsMethodName="GetConnectionString" name="MySessionStateStore" type="Microsoft.Web.Redis.RedisSessionStateProvider"/>
- 调整RedisConfig中的证书配置,使用
ClientCertificate属性替代事件注册:
static RedisConfig() { try { var options = new ConfigurationOptions { EndPoints = { "serverName:6379" }, ClientName = "SessionStateProvider", User = "acl-username", Password = "somelengthypassword", Ssl = true, SslProtocols = SslProtocols.Tls12, AllowAdmin = true, AbortOnConnectFail = false, ConnectTimeout = 10000, SyncTimeout = 6000, ConnectRetry = 3, CheckCertificateRevocation = false, ClientCertificate = new X509Certificate2("C:\\temp\\myclientcert.pfx", "test") }; conn = ConnectionMultiplexer.Connect(options); } catch (Exception) { throw; } }
- 确认Redis服务器已信任你的客户端证书,且ACL用户拥有Session相关键的操作权限。
内容的提问来源于stack exchange,提问作者Kavin A

