几周前,我们有一位客户联系我们说,有时当他创建活动时,它会以别人的名义创建!
我们做了一些故障排除,找不到任何东西。我们要求用户在下次遇到这些问题时与我们联系。他确实与我们联系,我们能够与他进行一次讨论,并亲眼看到问题。
不仅是活动,他在应用程序中被认可为其他人。他可以访问其他人应该访问的所有内容。就在那时我们意识到我们正在讨论混合问题。
关于我们的代码: 像任何其他应用程序一样,我们有一个简单的登录页面,用户输入电子邮件和密码,我们根据数据库对它们进行身份验证,如果它们有效,我们调用FormsAuthentication.SetAuthCookie()将当前用户ID保存在cookie中,我们让他进入。 / p>
BL.User currentUser = BL.User.Authenticate(txtUsername.Text, txtPassword.Text);
if (currentUser != null)
{
this.Session["NumberOfLoginTried"] = "0";
FormsAuthentication.SetAuthCookie(currentUser.UserID.ToString(), chRememberMe.Checked);
Response.Redirect(FormsAuthentication.GetRedirectUrl(currentUser.UserID.ToString(), false));
}
我们还使用以下代码在我们的应用程序中获取登录用户ID(当前用户)。
public static int GetCurrentUserID()
{
int userID = -1;
int.TryParse(HttpContext.Current.User.Identity.Name, out userID);
return userID;
}
是的,我们做了我们的家庭作业并用Google搜索,并看到了以下两个链接:
http://lionsden.co.il/codeden/?p=446
ASP.NET Session Mix-up using StateServer (SCARY!)
我们已禁用.aspx和.ascx文件的内核模式缓存和用户模式缓存,但这仍然存在。
P.S-该应用程序在带有IIS 7.5的Windows 2008 R2上运行。我们不使用无Cookie会话。
答案 0 :(得分:13)
我们遇到了一个非常类似的问题,这个问题随机发生,似乎无法重现。
问题原来是ASP.NETs页面缓存机制 - 在我们的例子中特别是<%@ OutputCache
标签。
我们使用了一条线
<%@ OutputCache NoStore="true" Duration="1" %>
这基本上意味着如果两个用户在1秒内访问同一页面,他们将看到相同的页面(包括其他用户的登录用户名)。因此,如果他们刷新了所述页面,他们就会得到正确的信息。
在我们的案例中,将所述行更改为
<%@ OutputCache NoStore="true" Duration="1" VaryByParam="*" %>
,在IIS中禁用内核缓存,如此链接(http://lionsden.co.il/codeden/?p=446)
并将以下行添加到相关网页的Page_Load
事件中:
Response.CacheControl = "private";
Response.ExpiresAbsolute = DateTime.Now.AddDays(-1d);
Response.Cache.SetCacheability(HttpCacheability.NoCache);
似乎已经为我们解决了问题。希望这可以帮助其他有类似问题的人。
答案 1 :(得分:4)
我们遇到了同样的问题,它是由IIS中的<clientCache/>
设置引起的,默认情况下无法添加Cache-Control: private
HTTP标头。缺少此标头意味着我们的表单身份验证cookie正由下游代理服务器缓存!因此,当我们的网站忙碌时,突然有大量用户突然以错误的用户身份登录!梦魇。
答案 2 :(得分:3)
如果完全删除<%@ OutputCache NoStore="true" Duration="1" VaryByParam="*"
(在从Master到aspx的行中的所有ascx文件中)也阻止了跨会话。只加载了一个带有outputcache指令的ascx,发生了跨会话。
在我的情况下,如果使用sessionstat InProc ore StateServer,如果有cookieless或cookie会话则无关紧要。
答案 3 :(得分:3)
我们工作的公司遇到了同样的问题。我们还意识到它是由输出缓存引起的,导致将其他人的SessionId发送给错误的人。
我们现在已将以下<caching>
元素添加到我们的web.config中。
<configuration>
[...]
<system.webServer>
[...]
<caching enabled="false" enableKernelCache="false">
</caching>
</system.webServer>
[..]
</configuration>
我们无法保证这会解决它,因为这个问题几乎不可能重现,但根据我们的研究,这应该可以解决它。
奇怪的是,可以在互联网上找到描述此问题的Microsoft文章的链接提供了一些常规页面,就像页面已被删除一样。
但是这篇微软文章似乎描述了与IIS 6相同的问题:
其中症状描述为:
请考虑以下情形。 Microsoft ASP.NET页面包含&lt;%@ OutputCache%&gt;指示。此外,ASP.NET页面生成包含Set-Cookie响应的HTTP标头。在此方案中,ASP.NET页面存储在Microsoft Internet信息服务(IIS)6.0中的HTTP协议堆栈(HTTP.sys)内核缓存中。因此,访问同一页面的多个用户可能会收到相同的Cookie。
<强>更新强>
我在Microsoft Premier Developer博客上发现这篇非常好的文章解释了很多:
ASP.Net Session Swapping – Why it happens and what can be done about it?
答案 4 :(得分:2)
因为你们都禁用了内核模式缓存,所以我想指出其他一些想法。
1)要正确使用HttpContext.Current.User.Identity.Name
,首先需要使用User.Identity.IsAuthenticated
2)在这一点上Session.Add("CurrentUser", currentUser);
你真正试图保存什么?
现在我认为问题在于缓存。页面存储在用户之间的某个位置,而另一个用户则混合在一起。您可以使用一些标题来避免中间代理计算机上的缓存。
Response.Cache.SetExpires(DateTime.UtcNow.AddYears(-2));
Response.Cache.SetNoStore();
Response.Cache.SetValidUntilExpires(false);
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.ExpiresAbsolute = DateTime.Now.Subtract(new TimeSpan(1, 0, 0, 0));
Response.Expires = 0;
Response.CacheControl = "no-cache";
Response.AppendHeader("Pragma", "no-cache");
另请注意,如果您的网页包含您不希望在用户之间共享的数据,则需要使用安全HTTPS页面,并通过在网络上添加<httpCookies httpOnlyCookies="true" requireSSL="true" />
将Cookie设置为仅在安全页面上可用的.config
另外,检查您是否在每1分钟运行清理路由的SQL服务器上保存会话。
为了能够找到更多信息,我建议在页面上存储一些隐藏文本,例如渲染的日期时间,也许是用户ID的最后4位数,以及你可能有什么其他可以帮助的东西你看看页面是否来自缓存。
答案 5 :(得分:2)
由于这似乎属于极其神秘的问题领域,也许是时候实现跨越式发展了。
您可以停止使用ASP.NET会话来完全存储您的标识符。
您有很多选项可以在哪里添加此信息。您可以选择将其加密到Forms Authentication票证的UserData属性中(我在生产之前已经完成了这项工作,它非常适合存储密钥,csv角色,甚至小json对象)。通过表单身份验证票证,您可以直接将信息写为自己的cookie。你也可以完全绕过cookie。
如果您选择绕过cookie,您基本上会进入无cookie的ASP.NET会话的类似区域。您有几个选项,您可以将用户标识符作为查询参数分隔每个URL。另一种选择是创建一个HttpModule,它将隐藏的表单输入添加到包含登录用户标识符的每个页面响应中。
如果您沿着无cookie路径前进,请确保无法将您的站点用作HTTP,并且每个请求都是HTTPS。更特别是如果您使用查询参数方法。
答案 6 :(得分:0)
我已经在这里回答了问题,但事实证明我的另一个解决方案(禁用输出缓存)并没有真正解决我们的问题。
因为在问题中声明缓存是关闭的,所以唯一可能产生这种情况的其他可能的(AFAIK)错误就是我们案例中的真正罪魁祸首:我们在{{中使用私有变量1}}。
因为这些是缓存的,以这种方式存储来自用户的私人/个人数据也会导致会话混淆!
这个答案描述了我们的问题以及如何解决它:
https://stackoverflow.com/a/8937793/1864395
另外,我认为我们能够通过同时为多个用户运行Apache JMeter来重现问题。这是一个非常好的工具(虽然不是真正用户友好/直观)用于(除其他外)压力测试。 这可能是诊断会话混淆的唯一方法!