views:

634

answers:

2

Hi all,

I'm working on a project which uses user authentication. I'm facing a issue with my AJAX requests if there is no authenticated session present when the request is made.

I've a session timeout of 3min, so if the user keeps idle for 3 min then do some action which causes a AJAX request then the request will fail and return a 403 error. Here What I'm planning to do is intercept all the AJAX request from the page and sent a ping to the server which will return a JSON object saying whether there is a valid session. If there is one then the client will continue with the current request else it will reload the current page which will take the user to the login page and the user has to provide the credentials again.

Here is my implementation.

$("#param-ajax").ajaxSend(function(evt, request, settings) {
var pingurl = GtsJQuery.getContextPath() + '/ping.json';
var escapedurl = pingurl.replace(/\//g, "\\/");

var regexpr1 = eval('/^' + escapedurl + '\\?.*$/');
var regexpr2 = eval('/^' + escapedurl + '$/');
// Proceed with the ping only if the url is not the ping url else it will
// cause recursive calls which will never end.
if (!regexpr1.test(settings.url) && !regexpr2.test(settings.url)) {
    var timeout = false;
    $.ajax({
                url : pingurl,
                cache : false,
                data : {
                    url : settings.url
                },
                async : false,
                complete : function(request, status) {
                    if (status == "error") {
                        try {
                            // GtsJQuery.getJsonObject() converts the string
                            // response to a JSON object
                            var result = GtsJQuery
                                    .getJsonObject(request.responseText)
                            if (result.timeout) {
                                timeout = true;
                                return;
                            }
                        } catch (e) {
                            // ignore the error. This should never occure.
                        }
                    }
                }
            });
    // Reload the window if there is a timeout -- means there is no valid
    // sesstion
    if (timeout) {
        window.location.reload();
    }
}
});

Here everything work fine included the window.location.reload(), but the original ajax request is not aborted. Since the original AJAX request is not aborted after the page reload is triggered, the AJAX request also is sent to the server. I want some mechanism which will allow me to abort the original request if the timeout turns out to be true.

This post offers some answer, but the issue remains with the third party plugins like datatables which uses AJAX. We cannot write a error handler for those AJAX requests.

Thank you.

+2  A: 

If I am understanding the situation, you do not need any of that. In your original ajax request, simply add an error function that will redirect the user.

errHandler = function(XMLHttpRequest, textStatus, errorThrown) {
      if( textStatus.match(/forbidden/i) ) {
        redirectUserToLoginHere();
      }
}

$.ajax({

    success: yourFunctionHere,

    error: errHandler
})

Then you might be able to make some ajax wrapper which always has that errHandler so you don't have to place it in every single ajax call.

EDIT:

after some experimentation, if an 'ajaxSend' handler throws an Error, then the original request will never be sent.

Also, if the handler does

document.location = '/login';

then the original request is never sent.

Hopefully that helps :)

Thr4wn
The problem is I'm using third party tools like datatables which internally uses AJAX to fetch data. I cannot write a error handler there, again I do not want every request to handle this case separately.
Arun P Johny
+2  A: 

I changed my concept now, I'm checking for the xmlHTTPRequest in the server side using the request header 'x-requested-with'.

If it is a xmlHTTPRequest then 'x-requested-with' will have the value 'XMLHttpRequest'. Both the javascript libraries(EXTjs and jQuery) I'm using sets this header correctly.

Here is my server side code

boolean isAjaxRequest = StringUtils.endsWithIgnoreCase(request.getHeader("x-requested-with"), "XMLHttpRequest")

EDIT

If the given request is a ajax request the response will be json data which will have status 403 and it will contain a key called timeout with value true ex: {timeout: true, ....}

Then we will handle this in the $.ajaxError() event handler will handle the error. If the error status is 403 and the timeout value is true then I'll reload the page.

Arun P Johny
I think still you have not addressed how you are handling the reloading portion of the problem. Using the 'x-requested-with' header is a good way to know whether the given request is a AJAX request
Robert