我在这里发布@Simon Mourier 的评论解决方案,his approval,作为 CW 答案,因为我发现建议的方法最合适且侵入性较小,因为它只是禁用了 SignalR 请求的会话。
一个积极的副作用是请求将被更快地处理,因为不需要启动和加载 Session 对象。
它仍然使用 IHttpModule 进行工作,并且更可取的位置可能是 AcquireRequestState 事件(虽然尚未经过个人测试),或者在使用 Session 对象之前引发的事件。
请注意,使用这种方法可能需要测试 Session 对象是否可用,然后才能访问其任何成员或存储的对象。
public class SignalRSessionBypassModule : IHttpModule
{
public void Init(HttpApplication application)
{
application.AcquireRequestState += OnAcquireRequestState;
}
private bool IsSignalrRequest(string path)
{
return path.IndexOf("/signalr/", StringComparison.OrdinalIgnoreCase) > -1;
}
protected void AcquireRequestState(object sender, EventArgs e)
{
var httpContext = ((HttpApplication)sender).Context;
if (IsSignalrRequest(httpContext.Request.Path))
{
// Run request with Session disabled
httpContext.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Disabled);
}
}
public void Dispose()
{
}
}
这是另一种完全不同的方法,简单但非常有效。
不要依赖 Session/Auth cookie 来决定用户是否超时,而是使用 Cache 对象。这或多或少没有副作用,就像用户直接注销一样。
只需在 Web 应用程序代码开头的某处添加这个小 sn-p,当然 SignalR 不去的地方,您将能够检查缓存项是否存在并重新启动它(具有相同的到期时间会话超时设置的时间),如果没有,只需注销并删除 cookie/会话变量。
if (Request.IsAuthenticated) {
if (Cache[Context.User.Identity.Name] == null) {
// Call you logout method here...,
// or just:
// - Sign out from auth;
// - Delete auth cookie
// - Remove all session vars
} else {
// Reinitiate the cache item
Cache.Insert(Context.User.Identity.Name,
"a to you usable value",
null,
DateTime.Now.AddMinutes(Session.Timeout),
Cache.NoSlidingExpiration,
CacheItemPriority.Default,
null
);
}
在您的用户登录方法中,您只需添加它,即可首次创建缓存项
// Insert the cache item
Cache.Insert(Context.User.Identity.Name,
"a to you usable value",
null,
DateTime.Now.AddMinutes(Session.Timeout),
Cache.NoSlidingExpiration,
CacheItemPriority.Default,
null
);