why my session didn't get expired? - asp.net

I created an empty mvc3 project.
It has one controller ("home") and 2 actions ("index", "about")
I am using sqlserver to save my session.
here's my config file.
<sessionState mode="SQLServer" cookieless="false" timeout="1" sqlConnectionString="Data Source=localhost;Integrated Security=True;MultipleActiveResultSets=False">
time out is 1 min.
in index page. i created a session
Session["currentTime"] = DateTime.Now.ToString();
in my about page, I write it out in the view.
#Session["currentTime"]
First time, I opened up the about page, current time shows up. I leave the page alone for 5 mins, then go back refresh it. the old currentTime still there. I set timeout to be 1, so it should expired now and should show nothing on the page.
maybe I totally misunderstood how session works. please tell me why session value still there after its expired.
Edit:
its not the cache. I added following code to disable cache. still have problem.
<meta http-equiv="cache-control" content="max-age=0" />
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="expires" content="0" />
<meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
<meta http-equiv="pragma" content="no-cache" />
I think I found hte problem, not sure how to fix it.
I cleared my cache from Chrome. opened up "/home/index" page to create session, then go to "/home/about" page. check the DB. there's one session created. double checked "created" and "expires" field. confirmed that it will expired after one min.
then I walked away from my computer for 5 mins. after I come back and refresh the "/home/about" page. Session still there, not expired. query my Session table, notice that "expires" field changed to 1 min + the time I refresh the page. why expires field changed?????????
2nd Update:
I believe this is what the problem is. The SQL session provider doesn't actively monitor the Expires column in the session table. Instead, sessions aren't "officially" expired until they are removed from the table, which is done with a SQL Agent job that calls the DeleteExpiredSessions stored procedure. By default, the job is configured to run every 60 seconds.
i pretty sure my sql agent is not running. but dont know how to turn it on. please let me know if you have any ideas.

There are many things which could be possible over here. The time out as set in config is "1" min, so your session variable is bound to time out.
The situation that you are facing(and I am 90% sure), is the case of caching. Your Index page default controller action must be HTTP get. Put a button inside your page and then try to refresh your web page using button. The button will make a post to server. I am sure then the session variable would not persist.
UPDATE 2
Please see following the link to see how to turn on the Sql Agent. Please turn it on and let us know if it worked or not

Smells like caching issue. Which browser you are in?
The session you are using in browser is a 'guest' session which is initialized for all controllers (except sessionless, of cause). Even if it get expired, new one will be created and timespamp should be placed inside. So, each time you refresh the page, you should see current time.
EDIT: (after the post updated).
If think it works exactly right. According to this you need to set regenerateExpiredSessionId field of sessionState, to re-generate expired session id. Otherwise, the existing session object is simply re-newed and re-used.
EDIT 2:
The previous edit would be valid, if cookieless is true. In your code, you mentioned cookieless is false, but for some reason it still acts as cookieless = true. Are you sure you have right parameters in sessionState.

Related

enableViewStateMac="true" FAILS to Validate _ViewState

I have my web application where I have set the enableViewStateMac="true" under attribute in web.config. I was trying to validate different security aspects of view state.
However, there is one scenario, where enableViewStateMac="true" fails to validate the _ViewState has been changed. I am using the "TamperData" plugin of Firfox browser. Using Tamperdata, I completely remove the value of _VIEWSTATE and then POST the web request. The POST request gets posted successfully and page redirects to the next page successfully without any error.
Though, as per my knowledge and security testing so far for enableViewStateMac="true", It seems to me the EnableViewStateMac only works/validate weather _VIEWSTATE is being tampered or not. But it doesn't validate if _VIEWSTATE Value is being deleted/removed completely.
Is there is a way I can validate this also (that is if someone has completely removed the value of _VIEWSTATE)?
Thanks in advance,
Happy coding :)
When the page is generated, store a value in ViewState. Then, on post back, read that value back out. If __VIEWSTATE isn't present you'll receive a null value back at read time.

Session values are lost between calls

Due to an unknown reason, my website does not send ASP.NET_SessionId cookie to browser neither on local debugging IIS nor on deploying IIS, therefore my Session is always empty on each page. In IIS preferences 'Session state' is set to 'In process' (sorry, maybe not exact translation, I have localized IIS). Any ideas on this matter?
ADDITION 1: Well, I switched sessionState mode to <sessionState cookieless="UseUri" />. Url address in browser now contains (S(fn215g55r4kws155lbfaxf55)) tag, but Session property of the ASPX page is empty ANYWAY. So... my website is still sessionless without any obvious reason.
ADDITION 2. I created blank website on the same debug server and session cookie works okay there - values are persisted between calls. So, the problem is related to my main website or its web.config, I believe.
ADDITION 3. As mentioned #Damien_The_Unbeliever, the problem is really related to setting values. I do not know why, but session is completely ignores line Context.Session[promoCodeSessionKey] = (int?)promoCode.Id;. No cookie is send after this line. But if session is already created in another place and cookie is set, this line will work correctly.
ADDITION 4. I found the reason. See the answer below.
WOOHOO!! I found the reason! There was EnableSessionState="ReadOnly" directive in ASPX's <%# Page tag. Please pay attention, that a) because of this Session was not working on master page as well, and b) there are no exceptions!!

ASP.NET session lost after redirect but only with IE

Everything in italics is the original post, edits below are non-italicized
I am writing in C# using ASP.NET 4.0.
I am authenticating user credentials via SQL lookup and if valid I am storing the username in a session variable then redirecting the user back to the main page. Pretty simple.
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("/");
}
This is not yet over SSL as it's internal development at this point.
When I use Chrome Version "25.0.1364.172 m" I am properly redirected and I am "logged in". My screen is representative of that by showing me my user name and allowing me access to features that authentication allows.
When I use (32-bit) IE 9 Version "9.0.8112.16421" with the same server side code and procedure... When I do the redirect my session variable "username" is gone. In fact the session has a count of 0 for items. BEFORE the redirect the session variable is set and it is correct.
I have the same results on a Windows Server 2008 R2 64-bit box and a Windows 7 64-bit box.
I am using a single server hosting both IIS and SQL. I am not using a session server.
I have traced it out... the code is running exactly as desired up until the redirect. Receiving credentials, executing my stored procedure to validate... setting the session variable before redirecting (I can see the session and the variable and the value is correct).. and then redirecting... and as stated, with Chrome it works EXACTLY as desired... with IE the session is lost on redirect.
I have tried this as well with no success:
Response.Redirect("/", false);
So I'm convinced that something IE is doing, maybe with setting cookies on the client, that is causing a mismatch between the browser and the server session.
Should I not be doing a response.redirect??? And if I do a response.redirect, how do I keep the session from resetting? Once again, keep in mind this doesn't happen when I use Chrome.
Frustrating...
Thanks for any help!
NEW INFO
After attempting to turn off IE caching per an answer... I decided to output the sessionID to the browser so I could see what it was.
The behavior is more direct that the login and redirect...
In IE simply refreshing the browser with F5 causes a new session to be created on the server. Each refresh I receive a NEW session ID.
Testing this with Chrome I do not get a new session ID unless I call session.abandon, timing out my session or closing and restarting the browser.
I was only calling session.abandon when the user clicked log out, but have commented out that code (just in case) to ensure that I'm not abandoning it on accident.
Somewhere between actual page refreshes IE is presenting itself to the server for a new session... ARGH.
For example:
Chrome:
Before login: myjuzrmccerk1t4eakcliq14
After login: myjuzrmccerk1t4eakcliq14
IE:
Before login: unyebuc2ikac12xnhpssy0em
After login: unyebuc2ikac12xnhpssy0em
Refreshes with F5 or Ctrl-R:
one: ptjt42fjwzgdreyyyo3cmvrs
two: s1hd5aatl5yexeuc125aqhst
three: kbpflurcdcxubux3scmdm4k5
Update 2
I have changed the site to use "State Server" for the session and started the appropriate service... There is no change in behavior.
ANSWER
Since my rep is low.. .this won't let me answer my own question for another 3 hours... but here it is..
I found a fix... through trial and error.
InProc and StateServer in sessionstate both had the same results until I added "cookieless=true"
<sessionState mode="StateServer" cookieless="true" />
This causes the session state to be consistent in both Chrome and in IE (where the problems was) and my session ID no longer changes between page refreshes. I was unable to determine WHY this happens, but it is fixed nonetheless.. Thanks Mike and antinescience for your help!
InProc and StateServer in sessionstate both had the same results until I added "cookieless=true"
This causes the session state to be consistent in both Chrome and in IE (where the problems was) and my session ID no longer changes between page refreshes. I was unable to determine WHY this happens, but it is fixed nonetheless.. Thanks Mike and antinescience for your help!
There are some other reports that indicate that IE's caching mechanism (which is widely regarded as, well, not great) may be to blame here. Can you try appending the following to your page:
// Stop Caching in IE
Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);
// Stop Caching in Firefox
Response.Cache.SetNoStore();
...and see if that has any effect? The other alternative is you could do:
int randomNumber = new Random().Next(1, 1000);
Response.Redirect("/?nocache=" + randomNumber);
...just for testing. Heck, you could slap the date as numeric in to test as well.
i had the same problem for couple of days now and finally i knew the reason why the session was changed each refresh, first after using the Response.Redirect( URL ,false) method i realized that i was entering the URL as AbspoluteURI as "http:// ServerIP/File/Page.aspx" , i used the AbsolutePath method instead as "~/File/Page.aspx", and my problem was solved!! the IE thinks that the server was changed when you write AbsoluteURL instead of AbsolutePath, i wish this could help
I had the same problem with a webpage which was hosted inside an IFrame. Troubleshooting showed that the ASP.NET Session cookie was lost along the way, and it only happened when using Internet Explorer. When I opened up my webpage in a separate tab in IE everything worked fine.
The problem was caused by security in Internet Explorer. It will not persist cookies unless there is a P3P HTTP header. You can see the blocked URLs by going to IE->View->Webpage privacy report..., and there choose to show "Restricted websites".
I solved the problem by adding a dummy P3P header with every request. The header looks like this;
P3P:"Bogus P3P header because Internet Explorer requires one"
This is the same approach as facebook.com uses. Their p3p header looks like this;
p3p:CP="Facebook does not have a P3P policy. Learn why here: http://(...)/p3p"
See also Cookie blocked/not saved in IFRAME in Internet Explorer
I had this issue too, this SO response solved my problem. If your hostname has underscores (which seems to be invalid), IE seems to drop the session (!).

IE7 Classic ASP Cache

I have a classic asp website that uses Session variables to store login state ie. userid, isloggedin, etc. On logout, the session variables are reset and Session.Abandon() is called followed by a redirect to the login page. In IE7 I have noticed that after logout I can type in a previously visited url and see what appears to be a cached version of its state prior to the logout. Hitting ctl-f5 will reload from the server again and redirect to the login page. This is the behavior I want to occur even if the url is type in without the ctl-f5. Does anyone know how to get this behavior?
set the no-cache headers so that the pages do not get cached in the first place. see:
http://support.microsoft.com/kb/234067
I think mkoryak's answer (using no-cache headers) seems best. If you want certain pages to be seen only when a user is logged in, the best way is to instruct the browser to simply not cache the page. Furthermore, schemes such as tweaking cookies and using javascript do determine login state on the client are simply reinventing the wheel.
If you want to leverage some caching and your page isn't something that is constantly updating, a good compromise is to set the Response.Expires header to some value you deem appropriate (it's measured in minutes I believe).
I've had a similar problem before, but whenever I've clicked a link on that page, it's asked me to log back in.
You could try either resetting sessionID = "" or sessionID = "XYZ" and make XYZ something your code ignores on log out.
You could also try setting no-cache headers.
You could send no-cache however thats quiet a performance hit just to get what you want. I prefer Liams suggestion and ensuring that everything you do from that page requires you to be logged in, that way no one can do anything they shouldn't. What if its a email system though or similar, the people "could" view other peoples emails which are cached, in those instances then yes, not caching sensitive information is the way to go (you can't cache HTTPS pages by default for instance).
You could also include some javascript in the head which could check for the existance of a "logged in" cookie. This would run every time they loaded the page, if no cookie exists then JS could redirect you off to the login page. Not 100% fool proof but good enough. You logout page would need to clear this cookie and you login page set it.

Is there a way to keep a page from rendering once a person has logged out but hit the "back" button?

I have some website which requires a logon and shows sensitive information.
The person goes to the page, is prompted to log in, then gets to see the information.
The person logs out of the site, and is redirected back to the login page.
The person then can hit "back" and go right back to the page where the sensitive information is contained. Since the browser just thinks of it as rendered HTML, it shows it to them no problem.
Is there a way to prevent that information from being displayed when the person hits the "back" button from the logged out screen? I'm not trying to disable the back button itself, I'm just trying to keep the sensitive information from being displayed again because the person is not logged into the site anymore.
For the sake of argument, the above site/scenario is in ASP.NET with Forms Authentication (so when the user goes to the first page, which is the page they want, they're redirected to the logon page - in case that makes a difference).
The short answer is that it cannot be done securely.
There are, however, a lot of tricks that can be implemented to make it difficult for users to hit back and get sensitive data displayed.
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Cache.SetExpires(Now.AddSeconds(-1));
Response.Cache.SetNoStore();
Response.AppendHeader("Pragma", "no-cache");
This will disable caching on client side, however this is not supported by all browsers.
If you have the option of using AJAX then sensitive data can be retrieved using a updatepanel that is updated from client code and therefore it will not be displayed when hitting back unless client is still logged in.
Cache and history are independent and one shouldn't affect each other.
The only exception made for banks is that combination of HTTPS and Cache-Control: must-revalidate forces refresh when navigating in history.
In plain HTTP there's no way to do this except by exploiting browser bugs.
You could hack around it using Javascript that checks document.cookie and redirects when a "killer" cookie is set, but I imagine this could go seriously wrong when browser doesn't set/clear cookies exactly as expected.
From aspdev.org:
Add the following line on top of the Page_Load event handler and your ASP.NET page will not be cached in the users browsers:
Response.Cache.SetCacheability(HttpCacheability.NoCache)
Settings this property ensures that if the user hits the back-button the content will be gone, and if he presses "refresh" he will be redirected to the login-page.
DannySmurf, <meta> elements are extremely unreliable when it comes to controlling caching, and Pragma in particular even more so. Reference.
dannyp and others, no-cache does not stop caches from storing sensitive resources. It merely means that a cache cannot serve a resource it has stored without revalidating it first. If you wish to prevent sensitive resources from being cached, you need to use the no-store directive.
You could have a javascript function does a quick server check (ajax) and if the user is not logged in, erases the current page and replaces it with a message. This would obviously be vulnerable to a user whos javascript is off, but that is pretty rare. On the upside, this is both browser and server technology (asp/php etc) agnostic.
You are looking for a no-cache directive:
<META HTTP-EQUIV="PRAGMA" CONTENT="NO-CACHE">
If you've got a master page design going, this may be a little bit of a juggle, but I believe you can put this directive on a single page, without affecting the rest of your site (assuming that's what you want).
If you've got this directive set, the browser will dutifully head back to the server looking for a brand new copy of the page, which will cause your server to see that the user is not authenticated and bump him to the login page.
Have the logout operation be a POST. Then the browser will prompt for "Are you sure you want to re-post the form?" rather than show the page.
I don't know how to do it in ASP.NET but in PHP I would do something like:
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Cache-Control: no-cache");
header("Pragma: no-cache");
Which forces the browser to recheck that the item, so your authentication checking should be triggered, denying the user access.
It's a bit of a strain, but if you had a java applet or a flash application that was embedded and authentication was done through that you could make it so that they had to authenticate in, erm, 'real-time' with the server everytime they wanted to view the information.
Using this you could also encrypt any information.
There's always the possibility that someone can just save the page with the sensitive information on, having no cache isn't going to get around this situation (but then a screenshot can always be taken of a flash or java application).
For completeness:
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Cache.SetNoStore();
Response.Cache.SetExpires(DateTime.Now.AddMinutes(-1));
The correct answer involves use of setting the HTTP Cache-Control header on the response. If you want to ensure that they never cache the output, you can do Cache-Control: no-cache. This is often used in coordination with no-store as well.
Other options, if you want limited caching, include setting an expires time and must-revalidate, but these could potentially all cause a cached page to be displayed again.
See http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.4
Well, in a major brazilian bank corporation (Banco do Brasil) which is known by having one of the world´s most secure and efficient home banking software, they simply put history.go(1) in every page.So, if you hit the back button, you will be returned. Simple.
Please look into the HTTP response headers. Most of the ASP code that people are posting looks to be setting those. Be sure.
The chipmunk book from O'Reilly is the bible of HTTP, and Chris Shiflett's HTTP book is good as well.
You can have the web page with the sensitive be returned as an HTTP POST, then in most cases browsers will give you the message asking if you want want to resubmit the data. (Unfortunately I cannot find a canonical source for this behavior.)
I just had the banking example in mind.
The page of my bank has this in it:
<meta http-equiv="expires" content="0" />
This should be about this I suppose.

Resources