如何拦截爬虫及Bot的不必要会话创建?(Asp.Net Webforms环境)
解决方案:ASP.NET WebForms中拦截特定Bot的会话创建
针对你遇到的「无Cookie爬虫/Bot生成大量无效会话」的问题,我整理了两种可行方案,优先推荐第一种无需修改SqlInMemoryProvider的方法,简单高效:
方案1:用Global.asax事件提前拦截(无需改动Provider)
在WebForms的请求流程里,会话创建是有固定触发时机的,咱们可以在会话初始化之前识别Bot请求,直接禁用当前请求的会话状态,从根源上阻止SqlInMemoryProvider创建会话。
具体操作步骤:
- 打开你的
Global.asax文件,重写Application_PostAcquireRequestState事件——这个事件刚好在会话状态准备初始化前触发,是做判断的最佳时机。 - 编写Bot识别逻辑:可以结合「User-Agent特征」和「是否携带Cookie」两个条件(符合你说的“多数Bot不用Cookie”的场景)。
- 如果判定是目标Bot,调用
SetSessionStateBehavior禁用当前请求的会话状态。
示例代码:
protected void Application_PostAcquireRequestState(object sender, EventArgs e) { var context = HttpContext.Current; // 判断当前请求是否来自目标Bot if (IsTargetBot(context.Request)) { // 禁用会话状态,直接阻止会话创建 context.SetSessionStateBehavior(SessionStateBehavior.Disabled); } } // 自定义Bot识别逻辑,你可以根据实际需求调整规则 private bool IsTargetBot(HttpRequest request) { // 先检查User-Agent是否包含常见爬虫标识 var userAgent = request.UserAgent?.ToLower() ?? ""; var isKnownBot = userAgent.Contains("googlebot") || userAgent.Contains("bingbot") || userAgent.Contains("slurp"); // 再检查请求是否没有携带任何Cookie(对应你说的多数Bot不使用Cookie的情况) var noCookie = request.Cookies.Count == 0; // 满足任一条件即判定为Bot,你可以根据业务调整逻辑 return isKnownBot || noCookie; }
这个方案的好处是完全不用碰SqlInMemoryProvider,直接利用ASP.NET自带的请求生命周期机制实现拦截,兼容性好,测试起来也简单。
方案2:扩展SqlInMemoryProvider(方案1不生效时备选)
如果因为某些特殊场景(比如部分请求的会话状态初始化时机更早),方案1没能拦截成功,你可以尝试继承SqlInMemoryProvider,重写会话创建相关的方法,在创建会话前添加判断逻辑。
虽然这个Provider是非开源的,但它继承自标准的SessionStateStoreProviderBase,所以我们可以重写CreateNewStoreData方法——这个方法负责创建会话的存储数据,刚好可以在这里加Bot判断:
public class CustomSqlInMemoryProvider : SqlInMemoryProvider { public override SessionStateStoreData CreateNewStoreData(HttpContext context, int timeout) { // 先判断是否是目标Bot if (IsTargetBot(context.Request)) { // 如果是Bot,这里可以返回一个空的StoreData,或者直接触发禁用逻辑 // 注意:不同Provider的内部实现可能有差异,建议先在测试环境验证 return base.CreateNewStoreData(context, timeout); } else { // 正常用户请求,走原Provider的创建逻辑 return base.CreateNewStoreData(context, timeout); } } // 复用方案1的Bot识别逻辑 private bool IsTargetBot(HttpRequest request) { var userAgent = request.UserAgent?.ToLower() ?? ""; var isKnownBot = userAgent.Contains("googlebot") || userAgent.Contains("bingbot") || userAgent.Contains("slurp"); var noCookie = request.Cookies.Count == 0; return isKnownBot || noCookie; } }
然后在web.config里把原来的Provider替换成你的自定义版本:
<sessionState mode="Custom" customProvider="CustomSqlInMemoryProvider"> <providers> <add name="CustomSqlInMemoryProvider" type="你的命名空间.CustomSqlInMemoryProvider" connectionStringName="你的数据库连接字符串" /> </providers> </sessionState>
不过这个方案需要注意:因为SqlInMemoryProvider是非开源的,重写方法时可能会遇到内部实现的限制,一定要在测试环境充分验证后再上线。
小提示
- 记得优化你的Bot识别逻辑,避免误拦截正常用户(比如有些用户可能也禁用了Cookie,你可以结合User-Agent和请求IP、访问频率等特征综合判断)。
- 测试时可以用
curl或者Postman模拟Bot请求:不带Cookie、设置Bot的User-Agent,验证会话是否被正确阻止创建。
内容的提问来源于stack exchange,提问作者MS Dev
相关产品推荐
相关产品推荐

