I'm implementing the session sharing structure from this link for an ASP classic site to begin the gradual conversion process to ASP.NET. I'm trying to extend the cookie expiration time so that users do not get signed out of the site when the session expires. At the place where the cookie is created in SessionPage.cs I've added the line in the CreateNewSessionCookie() method:
cookie.Expires = DateTime.Now.AddDays(14);
Now this works fine, however, it only works if the user first visits an ASP.NET page, and then visits the ASP classic pages. It doesn't work if visiting an ASP classic page first (looking at the cookie through firefox confirms that different expiration values are given based on if I visit an ASP or ASP.NET page first.) I'm still a bit fuzzy on the mechanics behind this implementation as I don't have a complete understanding of session and cookie handling. However, I would have thought that the VB6 SessionMgr object is calling the SessionUtility DLL, and thus is using the same code to issue the cookie. I have re-registered the SessionUtility using gacutil, and re-exposed it using regasm. How else is the cookie being issued when a user accesses an ASP classic page? How can I change the expiration time?
This might be a total hack, but since you don't have any answers yet...
Iterate through the Request.Cookies collection in classic asp and find the session cookie (you should be able to figure out which one it is fairly easily). Then reissue that cookie Response.Cookies(sessioncookiename) = sessioncookievalue and set
Response.Cookies(sessioncookiename).Expires = Now() + 14
Related
I have inherited an Classic ASP Site and a "bolt-on" ASP.NET site...
NEITHER are using Authentication, BOTH sides have a manual "reinvent-the- wheel" (hard-coded) security system that validates the user/pw from a SQL 2000 database (i.e. "if the user is found via a SQL SELECT, let them in").
New development is in ASP.NET... and they have "integrated" the two sites via ONE login (described above) on the Classic ASP side... then passing a GUID (saved at the time of login to the users record) they validate the GUID on the ASP.NET side ("yes, this is the correct GUID, therefore this is my user... let them in").
Up until now this has been working ONE DIRECTION (Classic ASP to ASP.NET) only with no issues.
(Getting to the problem, bear with me...)
Now they want to perform the same basic design from ASP.NET to Classic ASP by updating the GUID, passing it back, where the lookup validates the user, send them to the correct Classic ASP page... (so the user can return to the Classic ASP side without re-loging-in, previously required) HOWEVER...
***HERE's THE PROBLEM
Session("UserID") is used on the Classic ASP side to (hard code) validate the user... then Response.Redirect is run to send them back to the page that they previously left via "sRedirectToString" ...
'user is found in DB, so send them to the correct page...
Dim sRedirectToString = 'the correct url
Call Response.Redirect (sRedirectToString)
HOWEVER, Session("UserID") gets cleared by IIS or IE (dun'no) and the (hard-coded) validation fails because Session("UserID") is NULL (blank)
Here's the simple (only) validation:
If Trim(Session("UserID") & "") = "" Then
'Session timed out
Response.Redirect('the denied page)
Else
Response.Write "<meta http-equiv=""X-UA-Compatible"" content=""IE=EmulateIE7"">"
End If
So, why are the Session Variables being cleared by a Redirect? (there is no other system authentication is being used).
There is no Session.Abort, nor any specific coding that is clearing Session("UserID").
But when Session("UserID") is tested (see code above) it is found empty and redirects to the DENIED.asp page.
So, hoping there is some property like "PersistSessionVariables" (or something) that I can set so they don't clear...
BUT THEY DO INDEED CLEAR IMMEDIATELY AFTER THE REDIRECT AND THIS IS CONFUSING TO ME.
I appreciate all the Wizards help!
A little background:
I have developed a web application in MVC3 that requires users to be logged in to access.
If the web page has been left for 5 minutes, a timer fires which makes a jQuery ajax call to the server, and returns a partial view which contains the logged in users email address, and a password textbox so that the user can re-enter their details before continuing to use the application.
I use Forms Authentication, with the cookie for it stored in the browser set to expire when the browser session closes (i.e. it does not have the Expires property set).
If I have the idle timer set to 10 seconds, or 1 minute, it works fine. If however I set it to 5 minutes, on the server the following is what I see:
HttpContext.Current.User.Identity.IsAuthenticated has value false
HttpContext.Current.User.Identity.Name has value "empty"
So I cannot get to the currently logged in users details.
Any ideas?
I have noticed that in my web.config, under the Authentication node, there is a timeout also set to 5 minutes which seemed to be affecting it. Hence why it worked fine for any requests below the 5 minutes mark. I changed this to 30 minutes and it appears at first glance to be working.
You can try keeping the settings of the user in web.config file, like isdebugmode,clientcode and fetch from there.
Dot net nuke is not a bad choice either.
Few weeks ago we had one of our customers contacting us saying that sometimes when he creates an activity it gets created under someone else's name!
We did some troubleshooting and couldn't find anything. We asked the user to contact us the next time he was experiencing these issues. He did contact us and we were able to do a gotomeeting with him and see the issue with our own eyes.
It was not only the activities, he was recognized as someone else in the application. He had access to everything that other person should had access to. That was when we realized we are having a session mixed up issue.
A little bit about our code:
Like any other application we have a simple login page that user enter email and password and we authenticate them against our database and if they are valid we call FormsAuthentication.SetAuthCookie() to save current user id in the cookie and we let him in.
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));
}
We also use the following piece of code to get logged-in user id (current user) in our application.
public static int GetCurrentUserID()
{
int userID = -1;
int.TryParse(HttpContext.Current.User.Identity.Name, out userID);
return userID;
}
And yes we did our homework and googled around and have seen the following two links:
http://lionsden.co.il/codeden/?p=446
ASP.NET Session Mix-up using StateServer (SCARY!)
We have disabled kernel-mode caching and user-mode caching for .aspx and .ascx files and this is still happening.
P.S- The app is running on Windows 2008 R2 with IIS 7.5. And we are NOT using cookieless session.
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!
The company that I work for is making a transition between classic ASP programs and ASP.NET programs for our intranet software. Eventually, everything will be written in ASP.NET, but because of time constraints, there are still a number of programs that use classic ASP.
To compensate we've written features that allow for redirects and autologins between classic ASP programs and ASP.NET programs. I've been starting to see a problem, though, with holding the session state for our ASP.NET software. If a user uses an ASP.NET program, then does work in a classic ASP program, then goes back to that ASP.NET program, often times, the user's authentication for the ASP.NET program is still in place, yet the user's session is lost, resulting in an error whenever a function is performed within the program.
I'm trying to capture the loss of the session state in global.asax's Session_End event, which would redirect the user to the login page, but that hasn't worked. Has anyone else faced a similar issue with users moving back and forth between classic ASP and ASP.NET and losing sessions? Is that even my real issue here? It's the only thing that I can see as being a problem.
EDIT
This is what we do to redirect users to an ASP.NET page from a classic asp page.
We create an MD5 hash based off of the userID and the date and send it to a redirect.aspx page via the query string. From there, the aspx page creates its own MD5 has based off of the userId and the date, both passed via the query string. If the 2 hashes are identical, the user is authenticated, and the program loads. Here is an example:
Classic ASP:
strDate = Year(Now()) & right("0" & Month(Now()), 2) & right("0" & Day(Now()), 2)
key = MD5(SessionUserID & strDate)
Response.Redirect "/redirect.aspx?key="&key&"&lpid="&ProgramID&"&unum="&SessionUserNum&"&uid="&SessionUserID&"&gid="&SessionGroupID
Redirect.aspx:
string key = Request.QueryString["key"];
//SetDesignModeState Variables:
if (getMd5Hash(Request.QueryString["uid"] + DateTime.Today.ToString("yyyyMMdd")) == key)
{
Session["SessionGroupID"] = Request.QueryString["gid"];
Session["SessionUserNum"] = Request.QueryString["unum"];
Session["SessionUserID"] = Request.QueryString["uid"];
string appID = Request.QueryString["lpid"];
FormsAuthentication.SetAuthCookie(Request.QueryString["uid"], false);
//redirect to ASP.NET page...
I've done a similar thing to you: authenticating users from a legacy ASP application to an ASP.NET site. What would help, is if you could provide a little more detail (sample code, perhaps) of the process you've setup to do this with users coming from the legacy app to the ASPX app.
To give you a brief idea, in my implementation I've done the following:
Create an .ASPX page
The .ASPX page accepts HTTP POST values from a particular legacy ASP app only.
When a POST request is received, I extract the username/password values, then proceed to authenticate in the normal way. If the user is successfully authenticated, we issue a FormsAuthentication cookie to the user.
In reality, my implementation is quite a bit more complicated, using the database as a backing store (as both apps share a common data source) and a particular database field to store a random code which is sent from the classic app to the .NET side to further verify that the request received by the .NET app is valid.
EDIT:
Try manually setting your authentication cookie. Delete the line:
FormsAuthentication.SetAuthCookie(Request.QueryString["uid"], false);
Replace with:
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1,
Request.QueryString["uid"],
DateTime.Now,
DateTime.Now.AddHours(24),
false,
null)
string encryptedTicket = FormsAuthentication.Encrypt(ticket);
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
HttpContext.Current.Response.Cookies.Add(cookie);
See how you get on with that?
I'm working on an ASP.NET application and I'm having difficulty in understanding why a cookie appears to be null.
On one page (results.aspx) I create a cookie, adding entries every time the user clicks a checkbox. When the user clicks a button, they're taken to another page (graph.aspx) where the contents of that cookie is read.
The problem is that the cookie doesn't seem to exist on graph.aspx. The following code returns null:
Request.Cookies["MyCookie"];
The weird thing is this is only an issue on our staging server. This app is deployed to a production server and it's fine. It also works perfectly locally.
I've put debug code on both pages:
StringBuilder sb = new StringBuilder();
foreach (string cookie in Request.Cookies.AllKeys)
{
sb.Append(cookie.ToString() + "<br />");
}
this.divDebugOutput.InnerHtml = sb.ToString();
On results.aspx (where there are no problems), I can see the cookies are:
MyCookie
__utma
__utmb
__utmz
_csoot
_csuid ASP.NET_SessionId
__utmc
On graph.aspx, you can see there is no 'MyCookie'
__utma
__utmb
__utmz
_csoot
_csuid ASP.NET_SessionId
__utmc
With that said, if I take a look with my FireCookie, I can see that the same cookie does in fact exist on BOTH pages! WTF?!?!?!?! (ok, rant over :-) )
Has anyone seen something like this before? Why would ASP.NET claim that a cookie is null on one page, and not null on another?
This was happening because I was running the app under a different virtual directory. When I ran it on the original one, it worked.
I would suggest loading the IIS debug diagnostics tools. It is entirely possible that on that particular server there is a resource problem or unhandled exception that is killing that particular cookie AFTER it is added to the response but before it is flushed to the user. This is basically caused by a series of exceptions that occur in rapid succession causing rapid fail protection to shut down the w3wp.exe process that your page is running under. When the process is spooled back up to feed the response, the cookie is gone and all that goes out is the rendered html.
You might also try turning off rapid fail protection or altering memory settings/recycling settings on the application pool.