In my web app I'm using some session variables, which are set when I login:
e.g. Session("user_id") = reader("user_id")
I use this through my app.
When the session variable times out, this throws errors mainly when connecting to the database as session("user_id") is required for some queries.
How can I set my session variables so that once they are timed out to go to the login page or how can at least increase the length of time the are available?
I'm guessing you're using Forms Authentication. The trick here is to ensure that your Forms Authentication expires before the session does.
I wrote about this in this answer here:
How to redirect to LogIn page when Session is expired (ASP.NET 3.5 FormsAuthen)
For example:
Configure your Forms Authentication - this sets the timeout to 60 minutes:
<authentication mode="Forms">
<forms defaultUrl="~/Default.aspx"
loginUrl="~/Login.aspx"
slidingExpiration="true"
timeout="60" />
</authentication>
Extend Session expiry to a longer time:
<sessionState
mode="InProc"
cookieless="false"
timeout="70"/>
In your Login.aspx code behind you could also do a Session.Clear(); to remove stale session data before assigning session values.
In the past I've used a base page or master page on every page (making an exception for the login page) that reads a session token to see if a user is logged in currently.
If it ever reads a null it saves the current url and redirects to the login page.
After logging in it reads the saved url and redirects the user back to the requested page.
Increasing the session timeout value is a setting in IIS.
How can I set my session variables so that once they are timed out to go to the login page
Check if they are = null do a Response.Redirect("Home.aspx");
or how can at least increase the
length of time the are available?
Its in the web.config within the sessionState element
I think a lot of people wrap their session calls to provide a "lazy load" pattern. Something like this:
class SessionHelper
{
public static string GetUserId()
{
string userId = (string)System.Web.HttpContext.Current.Session["UserId"];
if( userId == null )
{
userId = reader("UserId");
System.Web.HttpContext.Current.Session["UserId"] = userId;
}
return userId;
}
}
Related
I am developing ASP.Net MVC application.
We have used sessionState mode SQLServer and i have set timeout to 20 minutes.
<sessionState mode="SQLServer"
sqlConnectionString="data source=127.0.0.1;user id=sa;password=sa"
cookieless="false"
timeout="2" />
Code is something like this in web config.
I have also set login page.
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" timeout="2880" />
</authentication>
Now when session expires i want to navigate user to login page.
I checked many things but i was unable to understand how it exactly works? and how can i navigate user login page on session expire?
It is working in InProc mode. I used it in same way and user is redirected to login on session expire.
But i am unable to accomplish same thing in SQLServer Mode.
I am unable to understand what i am missing?
I checked Session State and also found that Session timeout handled in SQLServer Mode
Edit :-
I want to redirect user to login page whenever another http request is executed for that session.
Ordinarily the browser has no idea what is going on on the server. Unless an HTTP round trip occurs, it will remember the state of the session from when the page was rendered.
In addition, you session cookie is probably HttpOnly, so there is no way for the page to check for the presence of a session cookie.
One way to accomplish what you want is:
Add a hidden iFrame to your page. Set the SRC of the iFrame to a handler in your web site
The handler doesn't have to do much except return a 200 OK, plus a refresh header set to a few seconds, so that the handler gets continually polled.
context.Response.AddHeader("REFRESH", "2");
Add framebreaker code to your login page
if (top.location != location) {
top.location.href = document.location.href ;
}
When a request for the handler occurs with an expired session, it'll get redirected to the login page via forms authentication; when the login page is returned, it'll break your iFrame and redirect the full window to the login page.
Or, you can do what everyone else does, which is wait for the user to request another page.
For me, changing the timeout value in the web.config file to anything didn't take place, and the reason was there were somehow some leftover old records in the ASPStateTempSessions table in ASPState database. I had to empty the table and only then my web.config changes took place. I wasted an hour trying to search for the cause so hope this helps someone.
So, run this:
delete from ASPStateTempSessions
Difference between InProc and SQLServer mode is that SQLServer relies on MSSQL job to remove the session. It actively doesn't prevent you from login again.
See Session State Providers
SqlSessionStateStore doesn't actively monitor the Expires field. Instead, it relies on an external agent to scavenge the database and delete expired sessions—sessions whose Expires field holds a date and time less than the current date and time. The ASPState database includes a SQL Server Agent job that periodically (by default, every 60 seconds) calls the stored procedure DeleteExpiredSessions to remove expired sessions.
I'm using the Membership API for my login system and a wierd thing has been bothering me. I allow user to choose whether to "Remember Me", which means whether to create a persistent cookie with one month expiration period.
In the Web.config, I wrote:
<authentication mode="Forms">
<forms timeout="60" />
</authentication>
This is supposed to be a default session cookie of 60 minutes.
In the code behind of the login page:
if(Membership.ValidateUser(UsernameTextBox.Text, PasswordTextBox.Text))
{
authCookie = FormsAuthentication.GetAuthCookie(UsernameTextBox.Text, RememberMeCheckBox.Checked);
if(RememberMeCheckBox.Checked)
authCookie.Expires = DateTime.Now.AddMonths(1);
Response.Cookies.Add(authCookie);
Response.Redirect(FormsAuthentication.GetRedirectUrl(UsernameTextBox.Text, RememberMeCheckBox.Checked));
}
The result however is strange. I seem to have created a persistent cookie of 60 minutes! How is this possible?
You are setting the cookie expiration time to be be 1 month, but the authentication ticket that it contains has not been modified. It has inherited the default value of 60 minutes from your web config.
You likely want to synchronize cookie expiration with the authentication ticket expiration, or alternatively set the cookie to have a very long expiry date.
What you need to do is
create a FormsAuthenticationTicket instance manually and set the
Expiration property of the instance.
Use FormsAuthentication.Encrypt() to encrypt the ticket
Add a cookie to the Response.Cookies collection containing the ticket, manually. (rather then using get/setAuthCookie(), which uses
the web.config settings).
Some example code is in the documentation for FormsAuthentication.Encrypt().
Can I write my code in the Session_End method when my session is timeout and I redirect users to the Login Page?
I am using Form Authentication method.
Currently I have create a "CheckSession()" method and calling on each page...
please suggest...
I've always placed the session check code in a master page for webform projects or, more recently, creating a base controller that has this method. Either way the goal is not to duplicate that code everywhere for obvious maintenance reasons.
I think you can manage this through settings in your web.config file without having to use code at all. Just ensure that the duration of your forms authentication cookie and your session are the same length. If your authentication session times out ASP.NET will automatically redirect a user to the login page.
Try:
<forms ... timeout="20" slidingExpiration="true" />
(slidingExpiration is true by default but I've specified it here because it must be true to replicate the timeout behaviour of sessions in ASP.NET)
and:
<sessionState ... timeout="20" />
Whats the best way to log out a user when a session ends or expires?
Thanks for any help.
It really depends on the desired functionality you're looking for. I'm going to assume you're using FormsAuthentication.
There's two separate things you need to be concerned about: the Session and the FormsAuthentication cookie. Unless I'm mistaken, both of these have separate timeouts.
If the problem you're having is that the session is timed out but the user still is authenticated, you could try a combination of the following:
1: Making sure the authentication cookie has the same timeout value as the session:
<authentication mode="Forms"><forms ... timeout="20" ... ><authentication>
<sessionState ... timeout="20" ... />
2: In your Page_Load event, check if the session has timed out:
if (context.Session != null && Context.Session.IsNewSession == true &&
Page.Request.Headers["Cookie"] != null &&
Page.Request.Headers["Cookie"].IndexOf("ASP.NET_SessionId") >= 0)
{
// session has timed out, log out the user
if (Page.Request.IsAuthenticated)
{
FormsAuthentication.SignOut();
}
// redirect to timeout page
Page.Response.Redirect("/Timeout.aspx");
}
(See http://www.eggheadcafe.com/articles/20051228.asp for information on detecting a session timeout)
If you want a more pleasant user experience, you could use javascript to initiate some sort of a modal UI popup after X minutes. This popup would simply allow a user to initiate a button-click which would trigger an AJAX postback on the server, thus extending their authentication and session cookie without them having to reload the page. I've never implemented this before but look, this guy made an ASP.NET AJAX control !
If you are using the .net Membership Provider, just set the Timeout-setting in the web.config
http://msdn.microsoft.com/en-us/library/h6bb9cz9(v=VS.100).aspx
Is it possible to control the behaviour of ASP.NET when the Session has expired? It seems that the default behaviour is sending the user to the website root. The desired effect would be to send the user to a custom "Session Expired" page.
To clarify, it's the SessionState that's expiring (set the timeout to 1 minute to quickly test it):
<sessionState mode="InProc" timeout="1"></sessionState>
The authentication cookie timeout is way higher, to avoid any mix-up:
<authentication mode="Forms">
<forms loginUrl="SessionExpired.aspx" slidingExpiration="true" name=".ttpASPXAUTH" timeout="58" protection="All"></forms>
</authentication>
I'm not sure about the whole Authorization ticket/session state problem, but an easy way to redirect someone to a particular page when their session has expired is to put code into the Application_AcquireRequestState event in the Global.asax file to check for a session variable and if it doesn't exist, redirect to your "session expired" page.
You can catch this in your global.asax in the Session_Start method.
I use something like this for simple sites:
if (!Request.Url.AbsolutePath.EndsWith("DEFAULT.ASPX", _
StringComparison.InvariantCultureIgnoreCase))
{
string newPage = string.Format("ErrorPage.aspx?ErrorMessage={0}", _
System.Uri.EscapeUriString("Your session has expired."));
Logger.InfoFormat("{0} Session expired or illegal page access attempted: {1}", _
Utility.StoreRegisterForLog, Request.Url.ToString());
Response.Redirect(newPage);
}
If they're not on the home page, she gets sent to the error page with a message saying her session has expired.