Asp.net Sessions Getting Crossed / Mixed Up

。_饼干妹妹 提交于 2019-11-27 18:36:39

We have just had a very similar problem, which occured at random, seemingly un-reproducibly.

The problem turned out to be ASP.NETs Page caching mechanism - in our case the <%@ OutputCache tag in particular.

There was a line we had used <%@ OutputCache NoStore="true" Duration="1" %> that basically meant if two users accessed the same page within 1 second of each other they would see the same page (including the logged in username of the other user). So if they refreshed said page, they got the correct information.

In our case, changing said line to <%@ OutputCache NoStore="true" Duration="1" VaryByParam="*" %>, disabling kernel caching in IIS as in this link (http://lionsden.co.il/codeden/?p=446)

and adding the following lines to the Page_Load event of the page in question:

Response.CacheControl = "private";
Response.ExpiresAbsolute = DateTime.Now.AddDays(-1d);
Response.Cache.SetCacheability(HttpCacheability.NoCache);

Seems to have solved the problem for us. Hopefully this helps someone else with a similar issue.

We had the same problem and it was caused by the <clientCache/> setting in IIS, which by default fails to add the Cache-Control: private HTTP header. The lack of this header meant that our Forms Authentication cookies were being cached by downstream proxy servers! So when our site got busy, all of a sudden a load of users would suddenly get logged in as the wrong user! Nightmare.

if removing the <%@ OutputCache NoStore="true" Duration="1" VaryByParam="*" at all (in all ascx files being in the line from Master to aspx too !!!) prevented from cross-sessions. having only one ascx with outputcache directive loaded, cross-sessions occured.

It did not matter in my case if using sessionstat InProc ore StateServer, if having cookieless or cookie sessions.

We had the same problem at the company I work at. We also realized that it was caused by output caching, which resulted in sending someone else's SessionId to the wrong person.

We have now added the following <caching> element to our web.config.

<configuration>
  [...]
  <system.webServer>
    [...]
    <caching enabled="false" enableKernelCache="false">
    </caching>
  </system.webServer>
  [..]
</configuration>

We can't guarantee this will solve it, because the problem is almost impossible to reproduce, but based on our research, this should solve it.

Strangely, the link to a Microsoft article describing this problem that can be found on the internet gives some general page as if the page has been deleted.

But there is this Microsoft article that seems to describe the same issue voor IIS 6:

An ASP.NET page is stored in the HTTP.sys kernel cache in IIS 6.0 when the ASP.NET page generates an HTTP header that contains a Set-Cookie response

Which describes the symptom as:

Consider the following scenario. A Microsoft ASP.NET page contains the <%@ OutputCache %> directive. Additionally, the ASP.NET page generates an HTTP header that contains a Set-Cookie response. In this scenario, the ASP.NET page is stored in the HTTP protocol stack (HTTP.sys) kernel cache in Microsoft Internet Information Services (IIS) 6.0. Therefore, multiple users who access the same page may receive identical cookies.

Update

I found this really good article at Microsoft Premier Developer blog that explains a lot:

ASP.Net Session Swapping – Why it happens and what can be done about it?

Because you all disabled kernel-mode caching, I like to point out some other thinks.

1) To correctly use the HttpContext.Current.User.Identity.Name, you first need to verify that your user is logedin by using the User.Identity.IsAuthenticated

2) in this point Session.Add("CurrentUser", currentUser); what are you actual try to save ?

Now I think that is the problem is on cache. The pages are stored somewhere in between your users and the one mix up with the other. Some of the headers that you can use to your page to avoid the cache on the middle proxy computers.

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");

Also I say that if your pages have data that you do not wish to share among your user you need to use Secure HTTPS pages, and set your cookies to be available only on secure pages by adding <httpCookies httpOnlyCookies="true" requireSSL="true" /> on web.config

Also, check if you save your session on SQL server that you scheduled run the clean up routing every 1 minute.

To been able to find some more information I suggest to store some hidden text on the pages, eg the date-time of the rendered, maybe a the last 4 digit of the userID, and what else you may thing that can help you see if the page come from a cache or not.

Since this seems to fall into the extremely arcane problem territory, maybe it's time for a leap.

You could stop using the ASP.NET session to store your identifiers altogether.

You have a bunch of options of where you could stick this information instead. You could choose to encrypt it into the Forms Authentication ticket's UserData property (I've done this before in production, it works great for storing a key(s), csv of roles, or even small json objects). Past the forms auth ticket, you could write the information directly as your own cookie. You could also bypass cookies altogether.

If you choose to bypass the cookies, you're basically entering into similar territory of the cookieless ASP.NET sessions. You have a couple of options, you could make the user identifier be apart of every single url as a query parameter. Another option would be to create a HttpModule that would add a hidden form input into every page response that contains the logged in user's identifier.

If you go down the cookieless path absolutely make sure it's not possible to use your site as HTTP and every single request is HTTPS. Even more especially if you use the query parameter method.

If you checked that output caching is not the problem

There is already on answer from me here, but as it turned out my other solution (disabling the output cache) did not really solve our problem for us.

Since in the question it is stated that caching is turned off, the only other possible (AFAIK) bug that can produce this is what turned out to be the real culprit in our case: we use a private variable in a ActionFilterAttribute.

And because these are cached, storing private/personal data from a user in this way can also lead to session mix-up!

This answer describes what our problem was and how to fix it:

https://stackoverflow.com/a/8937793/1864395

Also, I think it's good to mention that we were able to reproduce the problem by running Apache JMeter with a scenario for several users at the same time. It's a really nice tool (although not really user friendly/intuitive) used for (among other things) stress-testing. It's probably the only way to diagnose session mix-ups!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!