How to deal with session timeouts in AJAX requests

2020-05-26 03:54发布

问题:

I'm sure you're all familiar with the voting systems that use AJAX (Um... look right over there <----)

I have something similar and when you vote up or down it uses AJAX to request the new value from votes.php. The problem is that I am using a session to get the userid so a person can only vote once. What happens if they sit on the page for an hour and then vote so the session is no longer there? What would be a good way of handling this situation? Should I redirect their page to the login screen? If so, how can I do that from the votes.php page that is being referenced by the AJAX request? Am I overlooking a good way of handling this situation? Any advice would be helpful.

回答1:

Consider returning an http status of 401, and a JSON object detailing the reason. If you're using jQuery, that'll drop you to the error() callback, which you can then parse your object.

$.ajax({
  data: {},
  dataType: 'html',
  success: function(data) {
    // do whatever here
  },
  type: 'POST',
  url: 'myserver.com',
  error: function(XMLHttpRequest, textStatus, errorThrown) {
    // XMLHttpRequest.responseText has your json string
    // XMLHttpRequest.status has the 401 status code
    if (XMLHttpRequest.status === 401) {
      location.href = 'login.php';
    }
  }
});

I'm not familiar with PHP anymore, but this should work for just about any environment. You may have to suppress any automatic login form redirection though. In asp.net mvc the framework will see the 401 and push the default login form back, with a status of 200.



回答2:

You should only store a link to the users identity in the session. Use sessions to identify a user as x and then get user x's information from the database.

If your problem is with users sessions timing out then you should reconsider how you're using your sessions. Perhaps make them last until the browser closes? If you really want to make them a duration, then perhaps ping the server in intervals to keep the session alive.

Decide in your php script whether or not the user should be able to vote. If the session isn't set, or if they have already voted, return a message that you can identify with on the client side. If they already voted perhaps return "voted":"true" in a JSON object. Use JS to parse this object and understand what it means, taking the appropriate action. If the session isn't set, perhaps return "session_set":"false", and then make javascript redirect with a window.location = "login.php" etc.

Only increment the counter for the user on a successful return of a counted vote.



回答3:

This is an old thread, but I wanted to share my solution that is working really well.

In my framework the system redirects the user to the login form any time they try to access a page and the session has timed out or is not valid. I added to the top of the login form the following html comment:

<!--LOGINFORM-->

I created a wrapper for jQuery's $.ajax function which checks for this string on every request, and if it is there it shows a dialog popup saying that their session has timed out.

You can use this by just calling:

ajax.get('http://someurl.com', function(data){
    //Do stuff
});

Hope it helps someone.

var ajax = {
    check_login : function(resp){
        if (resp.substring(0, 16) === "<!--LOGINFORM-->"){
            // Show a popup or redirect them to login page!
            return true;
        }
        return false;
    },
    get : function(url, success){       
        if (typeof data =='undefined'){
            data = null;
        }

        $.ajax({
            url: url,
            type : 'GET',
            success : function(resp){
                if (!ajax.check_login(resp)) {
                    success(resp);
                }
            },
        });
    }   
};


回答4:

You structure the Javascript code that makes the Ajax request to accept a special result (say, -1 where a >=0 number would normally be, such as, a count of votes) to mean "sorry bub, you're timed out" and redirect to the re-login page (which can take as an optional parameter a message explaining to the user they timed out, &c).



回答5:

You could create a javascript function that could ping the server every 10 minutes via something like

setTimeout("Ping()", 60000); 

If you want to navigate the user to the login page if they connect with a faulty session then I would first verify the session and if it fails send a

header("Location: ...");

http://ca2.php.net/manual/en/function.header.php



回答6:

From a user perspective, the best solution is to pop up a message and login form, saying something like "You are not logged in or your session timed out". Digg does this very well.

As for the actual AJAX implementation, swilliams' 401 suggestion is solid. Alternatively, you can simply return a specific string on failure.