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

如何限制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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 01:30:56