I have implemented a session timeout using JQuery plugin and its been implemented like,
from page loads, it starts the timer and after 10 seconds, a popo-up will be shown.
something like this http://rigoneri.github.com/timeout-dialog.js/
function ShowTimeoutWarning(){
$.timeoutDialog({timeout: 1, countdown: 60, restart_on_yes: false});
}
setTimeout( 'ShowTimeoutWarning();', 100000 );
This code works fine when the user is idle for 10 seconds. But even though the user is doing some operation on the page, the popup is displayed, no matter the user is idle or not. I want this code to be run only when the user is idle.
Please help me on this regard.
Thanks!!!
Have a common javascript function that starts a setTimeout(). Note that this should be a time less than the session timeout defined in the web.xml. So when that timeout expires you give a warning to the user asking whether to invalidate the session or not. On every server call and every page reload you reset this setTimeout().
Hope this helps.
This is done with a timer and some JavaScript. When the timer expires on the page, the browser requests a URL that calls session.invalidate() on the server.
You should try the jQuery idleTimer plugin
http://www.paulirish.com/2009/jquery-idletimer-plugin/
<script type="text/javascript">
$(function () {
var timeout = 10000;
$(document).bind("idle.idleTimer", function () {
// function you want to fire when the user goes idle
$.timeoutDialog({ timeout: 0.25, countdown: 30, keep_alive_url: '/KeepAlive.aspx', logout_redirect_url: '/Signin.aspx', restart_on_yes: true });
});
$(document).bind("active.idleTimer", function () {
// function you want to fire when the user becomes active again
$.get('KeepAlive.aspx?date=' + escape(new Date()));
});
$.idleTimer(timeout);
});
</script>
Related
Recently I am working on a project which using ajax to call java servlet, and the request takes more than 10 sec to get the response, so I need to make sure during this time user won't be able to submit the form again, and my current approach is detect submit button click event and disable submit button, once success or error function is triggered in ajax, enable the button again, but this is not a good approach.
---- Edit ----
Sorry, I wasn't explain clearly, what I mean is this can stop non technical background user, but if any one intend to attack the site or whatever reason,
they can simply modify html code to enable the button, and do another submit,
Before I tried another way which set a cookie interval after form submit, and check the cookie when request finish, but just wondering whether there is any other way to do this, this question is purely for learning purpose.
Sorry for my English:)
I dont see anything wrong with disabling the button, that is what I frequently use, because this not only provides an indication that the system acknowledged your click but also prevent the user from clicking again.
If for some reason you dont like that you can disable the underlying method call something like this:
var isSubmitting = false;
function handleClick(){
if (!isSubmitting)
{
isSubmitting = true;
$.ajax(
"http://yourservice/submit" {
data: {someData:123},
contentType: 'application/json',
type: 'POST',
success: function(){
isSubmitting = false;
},
});
}
}
About your edit, the cookie sounds like a good approach, basically you need something that the server is going to pass to the client, and then check on submit. once that has been authorized the server will prevent processing of further requests with the same parameter.
But bear in mind that a malicious user would spawn thousands of requests to get cookies and then perform all the submissions anyway, so it is not really a defence against attackers, for that you would have to implement some form of throttling.
So in the end if you just want to prevent accidental submissions the button hide will suffice.
Something I have done and has been successful is a combination of what you described and preventing the function called by the button to execute twice. I do this by keeping a variable that gets set to true with the first request, then on subsequent request I check for it, if it's true, I don't do anything. Something like this:
var isRequestAlive = false;
var submit = function(){
if(!isRequestAlive){
isRequestAlive = true;
doAjaxStuff("", function(){
isRequestAlive = false;
})
}
}
I have a small web application with simple requirement that, I have a servlet and few JSP pages in my application.
When ever we give request to sevrlet it starts session on server with session timeout 1minute, then it displays one JSP page.
After session timeout on server I want to automatically display sign out JSP page in the browser how can we achieve this.
To add to Jhash
You have to have a timer javascript function on every jsp of your application (you can keep it in a .js file and include it)
Your session on the server can be about 30 minutes and your javascript timer can be around 2 to 5 minutes because even if a cached html page is shown, it would find out the situation within 2 minutes
Hope you are not relying on this for securing the application. You should still check on serverside that the user session is valid before letting the user use your application (the javascript should be only for convenience)
Edit:
Example of guessing timeout in JS and then navigating the user out:
var lastActiveTimeMs = new Date().getTime(); //This is set to current time on page load
var SESSION_TIMEOUT_MILLIS = 35*60*1000; //35 mins in milliseconds
var CHECK_TIME_MILLIS = 60*1000; //1 mins in milliseconds
setTimeout(fnCheckTimeout, CHECK_TIME_MILLIS); //Check the timeout once in a minute
function fnCheckTimeout(){
var curMs = new Date().getTime();
if( (curMs-lastActiveTimeMs)>SESSION_TIMEOUT_MILLIS ){
window.location.href = 'signout.html';
}
}
//Keep updating lastActiveTime every time you do an Ajax call.
//Because server will keep extending the session for every page load or ajax call from client
For this you need to use javascript in your jsp page.
For example if your session timeout is 2 minutes on server, in JSP page also you need to create a timer with same time using javascript, after javascript timer timeout happens, you just need to refresh the page by using same javascript code. so when you refresh the page session timeout happened already on server so you can check for session on server and if session is expired redirect control to the page you want.
I'm working on implementing a web application, with Google Appengine as the backend, on which the expected behaviour is as follows:
User selects a couple of parameters for a complex analysis
User presses 'Start'
An initially empty 'response' page is returned to the user, but the processing continues
The analysis somehow continues on the server and as partial results are being computed they are shown / added in the response page.
I'm expecting the total computation to be around 30-40 seconds (so way under the 60 seconds required by Appengine).
Steps 1 and 2 are trivial. I know step 4 could somehow be completed using step AJAX, but I'm not sure how exactly I could implement step 3.
Thanks!
You can use the task queue and the datastore. You need 3 handlers:
The task handler, doing the hard work. It will store its progress in the datastore.
A handler that starts the task in the background and returns the 'blank' page
A handler to get the status
Note: The page cannot be really blank. It must have javascript on it that checks the status. I think this is true with the Channel API too.
Anyway heres the code in Python:
class LongTaskStatus(ndb.Model):
is_complete = ndb.BooleanProperty()
percentage = ndb.FloatProperty()
messages = ndb.StringProperty(repeated=True)
class LongTaskHandler(webapp2.RequestHandler):
def get(self):
# Query for existing status model or create a new one
# Does work ...
# Update progress
status = LongTaskStatus()
status.messages.appen('Still busy...')
status.put()
# Does work ...
class StartHandler(webapp2.RequestHandler):
def get(self):
# start the task
taskqueue.add(url='/longtask')
# Return a page which uses javascript to check the progress every few seconds
template = JINJA_ENVIRONMENT.get_template('taskprogress.html')
self.response.write(template.render(template_values))
class CheckTaskStatus(wenapp2.RequestHandler):
def get(self):
query = LongTaskStatus.query().fetch(1)
result = {}
if query:
status = query[0]
result = {
'is_complete': status.is_complete,
'percentage': status.percentage,
'messages': status.messages
}
self.response.write(json.dumps(result))
and heres the "blank" page:
<!DOCTYPE html>
<html lang="en">
<body>
<div id="status"></div>
<script>
window.setInterval(function(){
$.get( "ajax/test.html", function( data ) {
$( ".status" ).html( data );
});
}, 5000);
</script>
</body>
</html>
Edit: Other option without Task Queue
If you have a unique way of identifying the task before it is started you could potentially speed this method up by not using the task queue api.
Heres how:
Call the LongTaskHandler via javascript
Redirect to a loading page, which calls CheckTaskStatus.
This should be faster than using task queues, but unfortunately you need a way to identify the task before it is started. eg userid, session etc
Check out the Channel API. It allows you to push messages from server to client.
I've a web page, where user can extend the session using AJAX call to server. If the application configured session timeout is for 30 minutes, he can extend the session for 5 minutes by pressing a button. When this user submits the pages, I need to reset this session timeout value back to the global session-timeout value.
Is it possible in Java to reset it?
or
Is it possible to read the global session-timeout value which is configured in web.xml?
EDIT:
I'm using the following code to extend the session
request.getSession().setMaxInactiveInterval(300000);
How do the user extend the session. I mean do you give a javascript alert/confirm box regarding it.
Ideally, session should automatically be extended when the user submits a request to the server.
setMaxInactiveInterval() in code and <session-config> in web.xml should do the stuff in normal scenario.
Share the exact situation of your application
EDIT:
Sending a dummy request to a JSP should automatically extend the session as session time out is measured in terms of inactive interval and the dummy request should discard the inactive interval till now.
I solved it by setting the default session as a session variable on execution of an action class, then using it to reset when ever required.
I'm not sure this is the right way to solve this. but it solve my issue, at least for now.
The time out and rest function is here and it will work accordingly to the service response.
Time setting function:
$rootScope.SessionTime =localStorage.getItem('mint');
$rootScope.tickDuration=1000;
$rootScope.myInterval=setInterval(function(){
$rootScope.SessionTime=$rootScope.SessionTime-$rootScope.tickDuration
//console.log("secs:::::"+$rootScope.SessionTime);
if($rootScope.SessionTime<300000 && $rootScope.tickDuration >0){
$('#session').modal('show');
$rootScope.tickDuration =0;
}
},$rootScope.tickDuration);
Time out function:
$scope.myTimeout = function(){
var sessionId=getcokkies.getsessionId();
$http({
url: config.apiUrl + '/user/refreshsession?sessionId='+sessionId,
method: "POST",
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: $.param({
'userId': parseInt(getcokkies.getUserId()),
})
}).then(function successCallback(response) {
//localStorage.setItem("mint", 600000);
//$rootScope.SessionTime = 600000;
clearInterval($rootScope.myInterval);
localStorage.setItem("mint", 600000);
$rootScope.SessionTime =localStorage.getItem('mint');
// console.log("after++++"+$rootScope.SessionTime);
$rootScope.tickDuration=1000;
}, function errorCallback(response) {});
}
Our application logs off after 30 min and gets redirected to login page,i am specifying session timeout in web.xml and using a requestProcessor for redirecting.I want to show to the user a message saying your session got expired once the session expires,how can i do that.Auto log off ?
I would like to prompt the error message on the page"The session is timeout, please login again" . Then how could I detect the session is timeout? will any methods trigger automatically?
Create an activity checker which checks every minute if any user activity has taken place (mouseclick, keypress) and performs a heartbeat to the server side to keep the session alive when the user is active and does nothing when the user is not active. When there is no activity for 30 minutes (or whatever default session timeout is been set on server side), then perform a redirect.
Here's a kickoff example with little help of jQuery to bind click and keypress events and fire ajax request.
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script>
$(document).ready(function() {
$.active = false;
$('body').bind('click keypress', function() { $.active = true; });
checkActivity(1800000, 60000, 0); // timeout = 30 minutes, interval = 1 minute.
});
function checkActivity(timeout, interval, elapsed) {
if ($.active) {
elapsed = 0;
$.active = false;
$.get('heartbeat');
}
if (elapsed < timeout) {
elapsed += interval;
setTimeout(function() {
checkActivity(timeout, interval, elapsed);
}, interval);
} else {
window.location = 'http://example.com/expired'; // Redirect to "session expired" page.
}
}
</script>
Create a Servlet which listens on /heartbeat and does basically just the following:
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
request.getSession();
}
to keep the session alive.
When you store the logged-in user in the session, it will be "automagically" logged out whenever the session expires. So you don't need to manually logout the user.
Create a Listener class implementing HttpSessionListener and define it in web.xml
This will notify you when any session is destroyed. Use the sessionDestroyed() method.
See a full example here:
http://www.mkyong.com/servlet/a-simple-httpsessionlistener-example-active-sessions-counter/
Either it may be simple servlet, spring-mvc or spring-security auto logout is not possible without perfect client side logic.
Considering application will have both type of request
AJAX and
form submission/page reload
Auto logout needs very calculated logic. Presenting my autologout functionality implementation with following
Advantages.
1. No extra call/request is used to achieve this. considering performance impact if more than 10k active users and extra calls to achieve auto logout.
2. One line configuration using tag.
3. Works flawlessly even if user opens multiple tab or multiple window.
4. It intimates you before 30 seconds of session invalidation, so if you have filled form and not submitted, you can keep session alive(extend session by one click). So user less likely to loose unsaved data.
Usage
1. Include auto logout script in required JSP pages as given below.
....
</body>
<jsp:include page="../template/autologout-script.jsp"></jsp:include>
</html>
2. Create a JSP page, autologout-script.jsp and add below code.
Note: No editing/configuring is required
<%#taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<script>
$(document).ready(function()
{
var timeOutTimeInSeconds = ${ timeOutTimeInSeconds };
var showTimerTimeInSeconds= ${ showTimerTimeInSeconds };
var sessionCheckIntervalId = setInterval(redirectToLoginPage, timeOutTimeInSeconds * 1000);
var timerDisplayIntervalId = setInterval(showTimer, (timeOutTimeInSeconds - showTimerTimeInSeconds) * 1000);
var badgeTimerId;
window.localStorage.setItem("AjaxRequestFired", new Date());
function redirectToLoginPage(){
//location.href = '<c:url value="/" />'+'${loginPageUrl}';
window.location.reload();
}
$(document).ajaxComplete(function () {
resetTimer();
});
$(window).bind('storage', function (e) {
if(e.originalEvent.key == "AjaxRequestFired"){
console.log("Request sent from another tab, hence resetting timer")
resetTimer();
}
});
function resetTimer()
{
showTimerTimeInSeconds= ${ showTimerTimeInSeconds };
console.log("timeOutTimeInSeconds : "+timeOutTimeInSeconds)
window.localStorage.setItem("AjaxRequestFired", new Date());
window.clearInterval(sessionCheckIntervalId);
sessionCheckIntervalId = setInterval(redirectToLoginPage, timeOutTimeInSeconds * 1000);
window.clearInterval(timerDisplayIntervalId);
timerDisplayIntervalId = setInterval(showTimer, (timeOutTimeInSeconds - showTimerTimeInSeconds) * 1000);
hideTimer();
}
function showTimer()
{
$('#sessionTimeRemaining').show();
$('#sessionTimeRemainingBadge').html(showTimerTimeInSeconds--);
window.clearInterval(timerDisplayIntervalId);
badgeTimerId = setInterval(function(){
$('#sessionTimeRemainingBadge').html(showTimerTimeInSeconds--);
}, 1000);
}
function hideTimer()
{
window.clearInterval(badgeTimerId);
$('#sessionTimeRemaining').hide();
}
});
</script>
3. Configure session attributes to configuring timeout setting
Note: Configure this after session creation. You can implement HttpSessionListener sessionCreated method and set the following configuration as per your requirement.
session.setMaxInactiveInterval(300);
session.setAttribute("timeOutTimeInSeconds", 300);
session.setAttribute("showTimerTimeInSeconds", 30);
4. Add below html for displaying timer.
Note: it can be moved to autologout-script template page if you are good at CSS. Hence you can avoid to add this in each and every page.
Include bootstrap or add your custom css.
<span class="badge badge-primary" title="click to keep session alive" id="sessionTimeRemaining"
onclick="ajaxSessionRefresh()" style="display:none;">
<i class="badge badge-danger" id="sessionTimeRemainingBadge" style="float:left">30</i>
<small>Refresh</small>
<i class="glyphicon glyphicon-refresh"></i>
</span>
That is all about a simple auto logout implementation.
You can download working example from my github repository
Autologout using simple servlet example
Autologout using spring-security java configuration example
Autologout using spring-security xml configuration example
Logic Explained
Case 1: On Page load
Here logic is simple, on page load set timer of interval equlas to maxInactiveInterval. after timeout redirect to login page.
Case 2: Keep track AJAX calls
Now considering AJAX requests, you can use .ajaxStart() or .ajaxComplete() callbacks of jquery so that if any ajax request is fired you can reset the interval.
Case 3: Tracking multi tab/window activity
Intertab communication is done to synchronize state of each tab. Used localStorage on change event.
Limitations/Improvements required
1. If maximum allowed session is one, if session is taken from another system, AJAX request will fail. It needs to be handled to redirect to login page.
2. Use ajaxStart() instead of ajaxComplete() to have exact sync of idleTime values between server and browser.
Requirements
1. Jquery
Alternatives to current implementation compared
1. Setting Refresh header in http response. (Not works for AJAX requests)
response.setHeader("Refresh", "60; URL=login.jsp");
Setting meta refresh tag in HTML (Not works for AJAX requests)
<meta http-equiv="refresh" content="60; url=login.jsp">
Configuring Activity checker
Keeps session alive by repeated AJAX request. Tracks idle time and makes logout request after timeout.
No doubt it is a good one with simple logic. But i want to just ink my observations.
Performance impact if 2 requests are made per minute to keep session alive and 50k active users. 100k requests per minute.
Intertab communication If two tabs are open, one tab is receiving activity but other tab is not receiving activity, that tab fires logout request and invalidate session even though activity is present in other tab. (But can be handled)
Force logout approach It is a client is dominated over server to invalidate session.
If you're using servlet sessions, you can check to see if the session the jsp / servlet is returning is new using the isNew() method. If yes, then the user's session has expired and you can display the relevant messages.
Include a javascript utility function inside your JSP and ping the server every 31 minutes.
The above mentioned utility function should be using setTimeout() JS function internally.
setTimeout ( "checkServerSession()", /* intervalInMilliSeconds */ 31000);
Note that
checkServerSession()
is a regular JS function which may fire HTTP requests. If the request is successful session exists otherwise show the prompt to the user.