0

Oh the wonderful MVC world....

I am trying to setup a timeout script for my website. Currently it seems to work but if the user wanted to extend the timeout time then move to another page it seems to have lost all of my session varibles I had saved.

FilterConfig.cs code:

public class IsAuthenticatedAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (rowCnt >= 1) //Making sure user has permissions to even view this site
            {
                System.Diagnostics.Debug.WriteLine("Current timeout: " + HttpContext.Current.Session.Timeout);
                System.Diagnostics.Debug.WriteLine("Session timeout: " + HttpContext.Current.Session["timeoutDate"]);

                if (HttpContext.Current.Session.Timeout == 20) //20 is the default timeout setting
                {
                    //It's the first time the user has visited the page so set timeout!
                    filterContext.HttpContext.Session.Clear();
                    filterContext.HttpContext.Session.RemoveAll();

                    HttpContext.Current.Session.Timeout = 1;
                    HttpContext.Current.Session["sessionVars"] = new initSessionVars().getSVars;
                    sessionVars sVars = HttpContext.Current.Session["sessionVars"] as sessionVars;

                    //Send them to the main page in order to populate the sessions and needed data
                    filterContext.Result = new RedirectResult("/"); 
                } else
                {
                    if (HttpContext.Current.Session["timeoutDate"] == null)
                    {
                        //No timeout has been saved so save it
                        int sessionTimeout = HttpContext.Current.Session.Timeout;

                        HttpContext.Current.Session["timeoutDate"] = DateTime.Now.AddMinutes(sessionTimeout);
                    }
                }                
            } else
            {
                //User was not found so they are NOT good to go!
                filterContext.HttpContext.Response.Redirect("~/Account/Unauthorized");
            }
        }
    }

I am using some jQuery in order to check for the timeout and present the user with a message box 10 seconds before it resets the session and sends them to a "sessions over" page.

_Layout.cshtml code:

 var idleTime = 0;
 var secondsLeft = 10;
 var sTimer;
 var idleInterval;

    $(document).ready(function () {
        idleInterval = setInterval(timerIncrement, @Html.Raw((Session.Timeout * 60) * 1000));

        $(".sleepy-close, .sleepy-wake-up").click(function () {
            $(".sleepy-overlay").fadeOut('fast');
            clearInterval(sTimer);
            idleTime = 0;

            $.ajax({
                url: 'Home/sessionChk',
                type: 'POST',
                cache: false,
                dataType: 'json',
                data: {
                    continueSession: true
                },
                success: function (responce) {
                    console.log('done');
                    idleInterval = setInterval(timerIncrement, responce);
                    setVars();
                },
                error: function (responce) {
                    showNotify('error', 'An error of<br/>' + responce + '<br/>Has occurred. Please get in touch with me about this error.', 20000);
                }
            });
        });

        $('.sleepy-modal').click(function (event) {
            event.stopPropagation();
        });
    });

    function setVars() {
        idleTime = 0;
        secondsLeft = 10;
        $('#timer').html(secondsLeft);
    }

    function timerIncrement() {
        idleTime++;

        if (idleTime > 1) {
            $('.sleepy-overlay').fadeIn('slow');
            clearInterval(idleInterval);
            sessionTimer();
        }
    }

    function sessionTimer() {
        sTimer = setInterval(function () {
            $('#timer').html(secondsLeft);
            secondsLeft--;

            if (secondsLeft <= 0) {
                clearInterval(sTimer);

                $.ajax({
                    url: 'Home/sessionChk',
                    type: 'POST',
                    cache: false,
                    dataType: 'json',
                    data: {
                        continueSession: false
                    },
                    success: function (responce) {
                        //clear the full screen for user to input new data
                        console.log('done');
                    },
                    error: function (responce) {
                        showNotify('error', 'An error of<br/>' + responce + '<br/>Has occurred. Please get in touch with me about this error.', 20000);
                    }
                });
            }
        }, 1000);
    }

If the user clicks the "stay awake" button then it sends an AJAX request to Home/sessionChk which sends a true for the continueSession.

HomeController.cs sessionChk code:

public class HomeController : Controller
{ 
   [HttpPost]
   public void sessionChk(bool continueSession)
   {
       ActionExecutingContext filterContext = new ActionExecutingContext();

       if (continueSession)
       {
           //Add more time to the session timeout
           HttpContext.Session.Timeout = 31;
       }
       else
       {
           //Lets go to the sessions exspiered page
           filterContext.Result = new RedirectResult("/");
       }
   }
}

So after it adds 31 more mintues I go ahead and pick another page within the site to visit. Once that page starts loading it tells me a session varible I am trying to load is no longer there.....

During the 1 minute the session starts when the page loads for the first time I can surf to any page within the site and all the sessions are fine and load up with the correct data so I know they have data at the beginning.

So what am I doing incorrectly since it doesnt seem to safe the session data when I extend the timeout time?

StealthRT
  • 10,108
  • 40
  • 183
  • 342
  • It seems like you are trying to replace authentication/authorization with session state. See [ASP.NET MVC Session Expiration](https://stackoverflow.com/questions/2595803/asp-net-mvc-session-expiration). Session state is [usually not the best way to track user profile data](https://brockallen.com/2012/04/07/think-twice-about-using-session-state/), is there any real reason why you need to store these variables on the server or is the entire purpose to extend the user's "session"? – NightOwl888 May 25 '17 at 15:40
  • extend it in the code above yes – StealthRT May 25 '17 at 15:54
  • I mean is there any other purpose? Why do you think you need Session state to do this? – NightOwl888 May 25 '17 at 16:20
  • Isnt that what its made for? – StealthRT May 25 '17 at 16:35
  • Session state is for storing state on the server-side. It is *not* for authentication/authorization of a web site. That is what [ASP.NET Identity](https://learn.microsoft.com/en-us/aspnet/identity/overview/getting-started/introduction-to-aspnet-identity) is for. You should only use session state if your app requires it because it comes at a high performance cost. My question is, do you have anything in `sessionVars` that is required to be in session state? What is in there? – NightOwl888 May 25 '17 at 16:55
  • my users do not have to log in as i am using windows auth for the page. aap.net idenity doesnt look like its suites for that either? – StealthRT May 25 '17 at 18:47
  • 1
    If you create a new MVC 5 application, you can choose the "Change Authentication" option to use Windows authentication. That said, Windows authentication does not time out because it is tied directly to logging into Windows. Given that fact, it is unclear what you are attempting to achieve here. You should edit your question and provide more information. It would be best if you put the variables somewhere that doesn't time out (cookies or the database, for example) and then you sidestep the timeout and performance issues altogether. – NightOwl888 May 25 '17 at 19:03

0 Answers0