ASP.NET在重定向后会丢失Session,但仅在IE浏览器下发生。

4

所有斜体字是原始帖子,以下修订内容不是斜体字

我正在使用ASP.NET 4.0中的C#编写代码。 我通过SQL查询验证用户凭据,如果有效,则将用户名存储在会话变量中,然后将用户重定向回主页面。非常简单。

if (!db.isValidLogin(userName, passWord))
    {
        //invalid login, show it!
        //just some code to tell the user invalid credentials
    }
    else
    {
        //show login successful!
        //update some items on the screen
        Session["username"] = userName.ToUpper();
        Response.Redirect("/");
    }

这还没有使用 SSL,目前仅为内部开发。 我使用 Chrome 版本 "25.0.1364.172 m" 时,我被正确重定向并且“已登录”。 屏幕显示我的用户名,并允许我访问身份验证所允许的功能。 当我使用相同的服务器端代码和过程时,使用(32位)IE 9 版本 "9.0.8112.16421" 时... 当我执行重定向时,我的会话变量 "username" 消失了。 实际上,该会话项数为 0。在重定向之前,会话变量设置正确。 我在 Windows Server 2008 R2 64 位框和 Windows 7 64 位框上获得相同的结果。 我正在使用单个服务器托管 IIS 和 SQL。我未使用会话服务器。 我已将其跟踪出来...代码运行得完全符合要求,直到重定向。 接收凭据,执行我的存储过程以进行验证...设置会话变量后重定向(我可以看到会话、变量和值都是正确的)...然后重定向...如上所述,使用 Chrome 完全按照预期工作...使用 IE 时,在重定向时会话会丢失。 我也尝试了这个但没有成功: Response.Redirect("/", false); 所以我确信IE正在做一些事情,也许是在客户端设置 cookie,从而导致浏览器和服务器会话之间出现不匹配。 我不应该使用 response.redirect 吗?如果我使用 response.redirect,如何保持会话不被重置?再次请记住,当我使用 Chrome 时不会发生这种情况。 令人沮丧... 感谢您的任何帮助!
新信息
尝试按照答案关闭 IE 缓存后...我决定将 sessionID 输出到浏览器中以便查看它。
行为比登录和重定向更直接...
在 IE 中,只需使用 F5 刷新浏览器即可在服务器上创建新会话。 每次刷新,我都会收到一个新的会话 ID。
用 Chrome 进行测试时,除非我调用 session.abandon、超时我的会话或关闭并重新启动浏览器,否则我不会获得新的会话 ID。
我只在用户单击注销时调用 session.abandon,但已注释掉该代码(以防万一),以确保我没有意外放弃它。
在实际页面刷新之间的某个地方,IE正在向服务器呈现自己以获取新会话...啊。
例如: Chrome: 登录前:myjuzrmccerk1t4eakcliq14 登录后:myjuzrmccerk1t4eakcliq14
IE: 登录前:unyebuc2ikac12xnhpssy0em 登录后:unyebuc2ikac12xnhpssy0em

按下F5或Ctrl-R刷新: one: ptjt42fjwzgdreyyyo3cmvrs two: s1hd5aatl5yexeuc125aqhst three: kbpflurcdcxubux3scmdm4k5

更新2

我已将网站更改为使用“状态服务器”作为会话,并启动了相应的服务......但行为没有改变。

答案

由于我的声望较低...这让我无法在另外3个小时内回答自己的问题...但是这就是解决方法。

我通过试错找到了解决方法。

在sessionstate中,InProc和StateServer的结果都相同,直到我加入了“cookieless=true”选项。

<sessionState mode="StateServer" cookieless="true" />

这样做可以使会话状态在Chrome和IE(存在问题)中保持一致,我的会话ID在页面刷新之间不再改变。我无法确定为什么会发生这种情况,但它已经被修复了。感谢Mike和antinescience的帮助!


为什么不直接使用 FormsAuthentication.RedirectFromLoginPage(userName.ToUpper(), true); 而忘记会话呢... 这并不是处理身份验证的最佳方式。 - MikeSmithDev
我不使用那种类型的重定向,因为登录“表单”实际上位于更新面板中,它会以伪模态框(使用jQuery)弹出,然后进行回发,返回“无效登录”值或只是重定向到自身。这样做的原因与业务有关,而不是因为这是最佳方式。 - Adam Wood
最好将用户名保留在会话中...但是,目前看来问题不再是身份验证(在OP中从未如此),而是重定向。问题似乎是使用IE会导致服务器认为需要在任何页面更新时创建新的会话,即使只是简单地点击刷新也是如此。 - Adam Wood
我感谢Mike的帮助……我可能会转而使用那种方法……我现在更担心的是每次刷新页面都会创建新的会话……我想知道当100个人在一分钟内点击10个页面时IIS服务会是什么样子……IIS认为每个都是“新”的点击。我想知道为什么IE会导致这种情况,而Chrome则不会。 - Adam Wood
很高兴你澄清了这件事! - antinescience
显示剩余3条评论
5个回答

4

在sessionstate中,InProc和StateServer在没有添加"cookieless=true"之前都有相同的结果。

这会导致Chrome和IE(出现问题的地方)中的会话状态保持一致,我的会话ID在页面刷新之间不再改变。我无法确定为什么会发生这种情况,但问题已经得到解决。感谢Mike和antinescience提供的帮助!


2
一些其他报告表明,IE的缓存机制(被广泛认为不太好)可能是导致这里出现问题的原因。您可以尝试将以下内容附加到您的页面上:
// Stop Caching in IE
Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);

// Stop Caching in Firefox
Response.Cache.SetNoStore();

"...看看那是否有任何影响?另一种选择是你可以这样做:"
int randomNumber = new Random().Next(1, 1000);
Response.Redirect("/?nocache=" + randomNumber);

“…只是为了测试。嘿,你甚至可以把日期作为数字输入以进行测试。”

我会尝试做这件事并回报。感谢您的帮助。 - Adam Wood
好的,我刚试过了这些,不起作用。我将更新我的原始帖子以包含我得到的新信息... - Adam Wood

1
我最近几天遇到了同样的问题,最终找到了会话在每次刷新后更改的原因。首先,在使用Response.Redirect( URL ,false)方法后,我意识到我将URL输入为AbspoluteURI,如"http:// ServerIP/File/Page.aspx",而我改用了AbsolutePath方法,如"~/File/Page.aspx",我的问题得到了解决!当你使用AbsoluteURL而不是AbsolutePath时,IE认为服务器已更改,希望这可以帮到您。请注意保留HTML标签。

0

我曾经遇到过一个网页在IFrame中托管的同样问题。排除故障后发现,ASP.NET会话cookie在传输过程中丢失,而且只有在使用Internet Explorer时才会出现这种情况。当我在IE中单独打开我的网页时,一切都正常。

问题是由于Internet Explorer中的安全性引起的。除非有P3P HTTP头,否则它不会保留cookie。您可以通过转到IE->查看->网页隐私报告...来查看被阻止的URL,并选择显示“受限制的网站”。

我通过在每个请求中添加虚拟的P3P头解决了这个问题。该头看起来像这样;

P3P:"Bogus P3P header because Internet Explorer requires one"

这是与facebook.com相同的方法。他们的p3p头部看起来像这样;

p3p:CP="Facebook does not have a P3P policy. Learn why here: http://(...)/p3p"

另请参阅{{link1:Internet Explorer中IFRAME中的Cookie被阻止/未保存}}


0

我也遇到了这个问题,这个SO回答解决了我的问题。如果您的主机名带有下划线(似乎是无效的),IE会删除会话!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接