在第二个请求之前,Global.asax Session_Start不会在IIS 7.5上启动

时间:2018-06-19 12:15:59

标签: session cookies asp.net-mvc-5 iis-7.5 owin

在我维护的网站上,https://conservationx.com/

1)Global.asax Session_Start,只需检查特定名称(visitor)的cookie,如果不存在,我们将发布一个。

protected void Session_Start()
{
    var req = HttpContext.Current.Request;
    var cookie = request.Cookies["visitor"];
    if (cookie == null)
    {
        var cookie = new HttpCookie("visitor", sguid);
        cookie.Shareable = false;   // Do not store in outputcache
        cookie.Expires = DateTime.UtcNow.AddYears(1);
        response.SetCookie(cookie);

2)在本地Debug中,我可以访问第一个请求,并进入该程序-隐身窗口始终在第一个请求上为我设置Set-Cookie标头。

3)一旦部署,我将永远不会看到在第一次请求时发出Cookie。我始终在第二个请求上看到它。

4)除了看到Set-Cookie标头直到在DevTools的“网络”选项卡中的第二个请求才出现之外,我还添加了日志记录到Session_Start主体,并将其全部包装在try / catch中,记录了所有异常。这同样始终未能在首次访问时触发。这个特定的网站会在页面加载完成后检查您是否已登录,并调用/ account / navaccountinfo-新鲜的浏览器/隐身窗口将始终无法使Cookie集登陆该网站的任何页面,然后查看cookie最终在该次要负载上设置,并且确保我们的日志中充满了在该次要请求URL的请求上设置的cookie。

这是将ASP.Net MVC部署到IIS 7.5的已知问题吗?如果正在使用OWIN和Identity Framework会产生什么影响?

推测,我想知道这是否相关:

OutputCache VaryByCustom cookie value

我设置cookie.Shareable = false是因为访问者ID在每个浏览器中都是唯一的。无法通过服务器的OutputCache将其分发给多个人。已访问的初始页面(如/或/ about)已设置OutputCacheAttribute,并通过GET访问。后续的/ account / navaccountinfo是通过POST访问的,因此,显然从未缓存过。因此,我想知道这是否实际上是OutputCachecookie.Shareable = false之间的不良互动。

1 个答案:

答案 0 :(得分:0)

这不是一个好的答案,但这是一个答案,我对其他更优雅的解决方案非常感兴趣。

问题

我们没有在Dev中缓存太多或根本没有缓存,而是在服务器上缓存,因此Session直到Post被触发后才触发-用户看到了来自IIS的快速缓存响应,这意味着大多数Asp.Net管道永远不会启动,尤其是Session_Start。帖子总是在缓存中崩溃,瞧,第二次调用-始终是帖子-总是看到cookie集,并且总是看到Session的日志条目。

此外,事实证明,默认情况下,设置HttpCookie.Shareable = false本质上会在您的缓存中抛出一个炸弹,而且在Dev中不使用太多缓存,我们并没有真正看到此标志造成的重大损害

糟糕的解决方案(欢迎提出提案)

我们已经在大量使用OutputCache VaryByCustom了,在这里我们做了一些创造性的工作,例如为公众提供该网站的一个版本,并分别拥有自己的登录成员。有关其工作原理的详细信息超出了此问题的范围,但是足以说明我们在VaryByCustom中使用Global.asax

public override string GetVaryByCustomString(HttpContext context, string key)
{
    return VaryByCustomKeyHandler.HandleCacheKey(key, context, Application);
}

键只是我们的编译安全方式,用于指示我们希望对Controller Action进行哪种类型的变化,而我将跳过其详细信息,但是HandleCacheKey方法现在看起来像这样:< / p>

string uidInSetVisitorCookie = context.Request.ServerVariables["SetVisitorCookie"];
if (uidInSetVisitorCookie != null)
    return uidInSetVisitorCookie;   // Force vary

因此,如果该用户应该收到Cookie,则基本上我们告诉OutputCache该用户和该用户现在应该自己获得该页面的副本。为此,我们提供了一个恰好是其随机生成的Uid的缓存键。 Uid是在BeginRequest中生成的,我已经证实,即使OutputCache最终将要处理Response的情况下,它也会触发:

protected void Application_BeginRequest(object sender, EventArgs ev)
{
    var req = (Brass9.Web.Visiting.Req)HttpContext.Current.Request;
    string uid = AnonCookieManager.O.GetUid(req);
    bool hadNoCookie = String.IsNullOrEmpty(uid);
    if (hadNoCookie)
    {
        uid = (Brass9.ShortGuid.NewGuid()).ToString();
        AnonCookieManager.O.PutCookie(HttpContext.Current.Response, uid);
        req.ServerVariables["SetVisitorCookie"] = uid;
    }

因此,其中有许多灯光库调用,但是很快:

  • Req是Asp.Net所使用的2个令人讨厌的Request类的简单包装器类,它们有很多重叠但未能共享基类。
  • GetUid()从请求cookie中获取访问者cookie(如果有)。
  • ShortGuid is a lot like this

最重要的是,PutCookie()已被修改以参与此变通办法,例如:

var cookie = new HttpCookie(CookieName, sguid);

//cookie.Shareable = false;
// Cookies shouldn't be shared, but, we signal to vary the OutputCache instead
// of blowing up OutputCache

cookie.Expires = DateTime.UtcNow.AddYears(1);
response.SetCookie(cookie);