如何限制dbo.TempGetStateItemExclusive3重复调用及处理会话伪造攻击
解决方案:ASPState会话锁重试控制与会话伪造攻击应对
一、控制会话锁重试行为
默认ASP.NET的SQLServer会话模式下,dbo.TempGetStateItemExclusive3的重试是硬编码的500ms间隔无限重试,直到获取锁或请求超时。要限制重试,有两种可行方案:
1. 自定义SessionStateProvider
继承SqlSessionStateProviderBase重写获取会话的逻辑,加入重试次数限制:
public class LimitedRetrySqlSessionStateProvider : SqlSessionStateProviderBase { // 自定义最大重试次数 private readonly int _maxRetries = 10; protected override SessionStateStoreData GetItemExclusive( HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { int retryCount = 0; do { try { return base.GetItemExclusive(context, id, out locked, out lockAge, out lockId, out actions); } catch (SessionStateException) { retryCount++; if (retryCount >= _maxRetries) { // 重试耗尽后终止请求 locked = false; lockAge = TimeSpan.Zero; lockId = null; actions = SessionStateActions.None; return null; } Thread.Sleep(500); // 保持原重试间隔,可按需调整 } } while (true); } }
然后在web.config中替换默认Provider:
<sessionState mode="Custom" customProvider="LimitedRetrySqlProvider"> <providers> <add name="LimitedRetrySqlProvider" type="YourNamespace.LimitedRetrySqlSessionStateProvider" connectionStringName="ASPState" /> </providers> </sessionState>
2. 强化请求超时控制
你已设置httpRuntime executionTimeout="60",需确保以下配置配合生效:
- IIS集成模式下,修改站点高级设置的连接超时为60秒,与executionTimeout保持一致;
- 若存在异步请求,需在Action中通过
CancellationToken手动控制超时,或在应用程序池设置中调整队列长度,避免请求堆积; - 确认
httpRuntime的timeout属性与executionTimeout同步,防止冲突。
二、应对会话伪造攻击
从LockCookie异常高值可确认是单SessionId被高频伪造请求攻击,需从防护、清理、拦截三方面处理:
1. 强化SessionCookie安全
在web.config的sessionState节点添加以下配置:
<sessionState mode="SQLServer" timeout="20" cookieSameSite="Strict" requireSSL="true" <!-- 仅当站点使用HTTPS时启用 --> regenerateExpiredSessionId="true" />
cookieSameSite="Strict":防止跨站Cookie盗用;regenerateExpiredSessionId="true":过期SessionId自动生成新值,避免旧ID被复用。
2. 清理过期与异常会话
- 确保SQL Server代理的
AspState_Job_DeleteExpiredSessions作业正常运行(默认每分钟执行一次),自动清理过期会话; - 手动清理异常会话(LockCookie过高的记录):
DELETE FROM ASPStateTempSessions WHERE LockCookie > 1000;
3. 拦截高频异常请求
- URL Rewrite规则:在IIS中创建规则,拦截单SessionId短时间内的高频请求(如1分钟内超过100次),返回403;
- 自定义中间件拦截:在请求管道中检查SessionId对应的LockCookie值,超过阈值则拒绝请求:
public class SessionAbuseMiddleware { private readonly RequestDelegate _next; private readonly IConfiguration _config; public SessionAbuseMiddleware(RequestDelegate next, IConfiguration config) { _next = next; _config = config; } public async Task InvokeAsync(HttpContext context) { var sessionCookieName = ".ASPXAUTH"; // 替换为你的SessionCookie名称 var sessionId = context.Request.Cookies[sessionCookieName]; if (!string.IsNullOrEmpty(sessionId)) { using (var conn = new SqlConnection(_config.GetConnectionString("ASPState"))) { await conn.OpenAsync(); var cmd = new SqlCommand( "SELECT LockCookie FROM ASPStateTempSessions WHERE SessionId = @SessionId", conn ); cmd.Parameters.AddWithValue("@SessionId", sessionId); var lockCookie = await cmd.ExecuteScalarAsync(); if (lockCookie != null && int.Parse(lockCookie.ToString()) > 100) { context.Response.StatusCode = 403; await context.Response.WriteAsync("Session abuse detected"); return; } } } await _next(context); } }
在Startup中注册中间件:
app.UseMiddleware<SessionAbuseMiddleware>();
三、临时应急措施
若当前SQL Server IOPS已耗尽,可先执行以下操作缓解:
- 重启应用程序池,释放当前会话锁,减少重试请求;
- 临时扩容SQL Server磁盘IOPS(云环境);
- 暂停非核心业务请求,优先保障核心接口。
内容的提问来源于stack exchange,提问作者RCalaf
相关产品推荐
相关产品推荐

