0
votes

I have an Asp.net web application where I am using FormsAuthentication for User login.

I want to prevent multiple logins to the same user at the same time. For this I have set the FormsAuthentication timeout to 15 minutes and Session.timeout to 15 minutes.

When the user closes the browser without logging out, or if the user is inactive for 15 minutes, it is not firing the Session_End() event in global.asax.cs file. I want to update the database field in the Session_End() event.

Code for Login:

if (Membership.ValidateUser(username, password))
                {
                    FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
                        1,
                        username,
                        DateTime.Now,
                        DateTime.Now.AddMinutes(15),
                        false,
                        FormsAuthentication.HashPasswordForStoringInConfigFile(password, "SHA1"));

                    // Now encrypt the ticket.
                    string encryptedTicket = FormsAuthentication.Encrypt(authTicket);
                    // Create a cookie and add the encrypted ticket to the cookie as data.
                    HttpCookie authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
                    context.Response.Cookies.Add(authCookie);

context.Response.Redirect("/HomePage", false);
}

Global.asax.cs:

 protected void Session_Start(Object sender, EventArgs e)
    {
        Session["init"] = 0;
        Session.Timeout = 15;
     }
    protected void Session_End(Object sender, EventArgs e)
    {
        PersonObject person = new PersonObject();
       // calling the function to update entry in database
        person.ResetUserLoginStatus(HttpContext.Current.User.Identity.Name);
    }

Function to update entry in database:

 public bool ResetUserLoginStatus( string username="")
    {
        string sql = "UPDATE Person SET IsLogged=0 WHERE Person =  @Person";
        PersonObject person = new PersonObject();
        object id = person.ExecuteScalar(sql, new Dictionary<string, object>() {
            { "Person", (!string.IsNullOrEmpty(username)?username:User.Name )}
        }, "Person");

        return true;
    }

Web.config:

<authentication mode="Forms">
  <forms loginUrl="/Security/Login.ashx/Home" name="SecurityCookie" timeout="15" slidingExpiration="true">
  </forms>
</authentication>

<sessionState timeout="15" mode="InProc"></sessionState>

The problem is that when the browser is closed the ResetUserLoginStatus() method isn't called and I am unable to reset my value to 0. Since the field has not been reset to 0, that user won't be able to log in again.

Please suggest.

1
Post your code pleaseBrad
Closing the Browser will never trigger it. It will happen after at least your 15min timeout, could be longer.Henk Holterman
Yes. I waited for 30 minutes after browser closed. But still it did not trigger Session_End()user10807821

1 Answers

1
votes

Session_End is actually not that useful or reliable. For one thing, it only fires at the end of the pipeline processing when an HTTP request has been received and a response has been rendered. That means it does NOT fire for a user who has simply closed their browser. Also, the event will never fire except for certain types of session state-- it won't work with State Server, for example, or SQL-based session state. The bottom line is you can't rely on it to maintain an unambiguous "Is logged in" flag.

Instead, I would store a "last page request received" time stamp. You can then infer the value of a "is logged in" flag; any user who has submitted a request in the past 15 minutes is still logged in.