3

I have implemented the multiple device logout functionality. if someone changes the password from one device than if the same user is logged in other device than he should be automatically gets log out by clicking on any other page.

Below is the approach I have implemented it. Step 1: I have created the below static class to achieve it.

enter code herepublic static class SessionStateStoreProvider
{       
    public static List<SessionStateList> sessionStateProviderList;
    static SessionStateStoreProvider()
    {
        sessionStateProviderList = new List<SessionStateList>();
    }        
}


public  class SessionStateList
{
    public  string UserName { get; set; }
    public  string GUID { get; set; }

}

Step 2: On each successfull login i am storing it in SessionStateStoreProvider class.

            Guid sessionIdentifier = Guid.NewGuid();                
            SessionStateList objSessionState = new SessionStateList();
            objSessionState.GUID = Convert.ToString(sessionIdentifier);
            objSessionState.UserName = userName;
            SessionStateStoreProvider.sessionStateProviderList.Add(objSessionState);                 
            Session["SessionIdentifier"] = Convert.ToString(sessionIdentifier);

Step 3 : On successfully changing the password i am removing all the Guid's associated to the user.

        SessionStateStoreProvider.sessionStateProviderList.RemoveAll(x => x.UserName == userName);

Step 4 : I have created one Http Module which checks that the user request is valid or not.

string sessionIdentifier = Convert.ToString(HttpContext.Current.Session["SessionIdentifier"]);
       string userName = HttpContext.Current.User.Identity.Name;
       List<SessionStateList> stateList = SessionStateStoreProvider.sessionStateProviderList;
       bool isValidSession = false; isValidSession = stateList.Any(cus => cus.GUID == sessionIdentifier);
       if (isValidSession == false)
       {
   FederatedAuthentication.SessionAuthenticationModule.SignOut();
       }

This works fine in my testing Add to dictionary as there is only one server handling all the request. But it is not working in my production environment as there are 3 different WFE's handling the web request. From my log I found that each login request is being handled by different WFE's. I was logged in with 4 different browser at the same time but SessionStateProviderList logged only one active session.

 int numberOfActiveSession = 0;
 numberOfActiveSession = Convert.ToInt32(SessionStateStoreProvider.sessionStateProviderList.FindAll(x => x.UserName == userName).Count); 

How do i handle this scenario ? Which approach should I follow ? Does caching is the solution to this problem ? Any help would be highly appreciated.

Savan Patel
  • 357
  • 4
  • 14

1 Answers1

1

The static variables are the same only inside one pool and on one process of the pool.

To share data between process you need a common database file, or shared common memory. Both of them must be on a central computer that you access from all the pools/computers/process.

redis is an open source in-memory data structure store that used for this. Also MS SQL 2016 advertise that also use in-memory data for fast access.

Some more to read about static variables: Lifetime of ASP.NET Static Variable

Community
  • 1
  • 1
Aristos
  • 66,005
  • 16
  • 114
  • 150
  • 1
    My concern is I don't want to hit database on every request. – Savan Patel Sep 19 '16 at 21:11
  • @SavanPatel You and many other - but this is the only way. Redis is a way for fast in-memory data structure, also MS SQL 2016 have similar abilities, to keep on memory the data and not use too many IO disk - in all cases you need to use one central computer to handle that database and call them. – Aristos Sep 20 '16 at 08:13
  • Thanks for the suggestion Aristos. I will look into redis. – Savan Patel Sep 20 '16 at 12:48