In my app, one of the requirements is that each user ID is restricted to being unique. That is, if I have, say, 3 users named "admin", "manager", and "user1", each user can login only if there is no other user with the same ID currently logged in. (This is fairly standard practice in most end-user apps that I have seen,BTW.)
I'm using XavaPro (though it doesn't seem to matter from what I have seen) and in looking at the Addons files User.java and SignIn.java the closest that I have seen to being able to do this is the boolean "active" property in User.java, though that appears to be more of a "Active/Inactive User" flag than a "currently-logged-in" flag, which is more what I'm looking for.
Before I screw thing up too badly by modifying core OX/XP functionality, I wanted to see if anyone on the group here has addressed this before and, if so, what techniques you might have used.
PS - I'm currently in a straight-forward, basic Tomcat model so want to stay within this model for now, so any suggestions should be within that context.
Thanks in advance as always!
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi Gerry,
I cannot help you, as I never had contact with XavaPro, but I would like to ask you, how can you identify that the user is logged already or not?
Let's say that I logged in as "admin" and suddenly after that I lost my internet connection. For the server I am logged now. Then I go to another computer with a working connection and try to login. Will the server block me, because I just logged in in another machine?
Did you think about it already? I would really want to know if people faced this question already, and if they managed to solve it. Thanks!
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Carlson,
First, it should not matter whether it's OX or XP (I think...)
Second, as it exists, there is an internal activity timer that will automatically log a user out after X seconds of inactivity. Even outside that context, an administrator can reset the logged-in state of a disconnected user, though that should be a very rare occasion.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
So the solution would be something like this: You need to create a new class to replace SignInHelper. The method isAuthorized will check for the lastActivity field. If the lastActive was more than X seconds/minutes ago, and the user and password matches, it returns true, otherwise, false; You need to create a new action, let's call it activityAction on the parent of all application's controller (Typical, MyTypical controller, name it). This action will execute before-each-request; This action will update the lastActivity field of the user on the database with the actual time; You create an action for the user to reset the last activity
For the second step, instead of using the database, I think it could be better to use the session object, maybe it is better for the performance?
I hope I could help you!
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Carlson, in looking into the files, it appears that there is an exposed "count" method in the User class, which does not seem to be referenced elsewhere (that I have found so far :-) ).
In olden times, that was a fairly standard way of tracking. I.e. when User logs in, check count. If count > 0 fail login with "already logged in User" message. On logout, decrement count (or set to zero - I still think in device driver mode sometimes...).
Would that be practical and/or am I missing someting else?
Thanks again!
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi Gerry, I never saw something related to a "count" into the code... but I don't think that having a counter incresed/decresed by the login/logout user process should be enough for your goal... I could mention some drawback about this approach, here are somes: what when the user session get timed out?, or what when the user just close the browser?.. as you can figure out, the session destroyed process can be fired without your control. Anyway, at the end, there are several ways to implement what you want... without persist any data related.
So, here is one:
Create a class (maybe in your * .listeners package) that implements HttpSessionListener interface:
public class HandleHttpSessionListener implements HttpSessionListener {
public void sessionCreated(HttpSessionEvent event){
// TODO: Do nothing here
}
public void sessionDestroyed(HttpSessionEvent event) {
// TODO: Your decrement handler here
MyAppSingleton.getInstance().decSessionCounter(Users.getCurrent())
}
}
You should be tempted to add your increment logic to the sessionCreated method of the session listener, but believe me... it is better to increment in the login process to make sure the user is really loged in. Also, the sessionCreated method is sometimes called even when the user has not loged in. So, we use the listener to decrease only, because that way we will cover any manual or automatic logout.
Btw, take care about Users.getCurrent()... I have found some situations where it resturn null (meaning no user loged in), even when there was at least one user loged in.
Add an entry to your listeners.xml file, just add the file if you don't have it in your project yet, just next to your web.xml (why not directly to your web.xml?, well... check the wiki about that):
Then you use the Singleton in your HttpSessionListener's sessionDestroyed method to decrement the session counter by user.
Go to your login process and add code to use the singleton for increment the corresponding session by the user loged in. It could be done in the SignInAction plugin acction (once the user has been validated)... you should be better use the User object (created in the login process) and user.getName() here (instead Users.getCurrent()), because I think Users.getCurrent() will return null at this stage.
Finally, in the same process login (at the begining), you can add a check to see if you allow the coming login to be allowed to continue or will be rejected because "N concurrent session allowed only".
So, I have not tested all that... but seems to work.
Just try and then let me know how you going.
Going beyond your original requirement, you could have a number property in your global app Preference module (or .properties) that define how many concurrent session for the same user you want to allow.
Regards,
Last edit: Hayrol Reyes 2016-04-30
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Preventing the user log in more than once is not a lightly task, there are
several reasons on why it is not easy to safely implement it. Sometimes you
must prevent user automatic log out, as a matter of fact, this is a common
practice for non critical applications, basically as long as a user has a
browser opened the session will remain active. That is why besides 'truly'
know if the user is logged in, some sort of remote log out should be
implemented. Why? Imagine that you user logged in his computer at home left
the session opened. If the session timeout is short, there is no problem,
but if no, you get the idea.
Personally, I think it would be a great feature to have in XavaPro.
There have always been issues with users failing to log out, connections broken, etc., but the benefits - to me - outweigh the those issues. Basically, of course, it enforces the ability of the app to verify that ThisUser performed ThisOperation, and no one else.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Finally this feature is implemented in XavaPro and it will available for v7.3, in April 2024, just the next month.
How we solved the problem of other opened sessions? We take a simple approach, when a user logins his other sessions are invalidated. So we don't have the problem when the user closes the browser without clicking in logout.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
In my app, one of the requirements is that each user ID is restricted to being unique. That is, if I have, say, 3 users named "admin", "manager", and "user1", each user can login only if there is no other user with the same ID currently logged in. (This is fairly standard practice in most end-user apps that I have seen,BTW.)
I'm using XavaPro (though it doesn't seem to matter from what I have seen) and in looking at the Addons files User.java and SignIn.java the closest that I have seen to being able to do this is the boolean "active" property in User.java, though that appears to be more of a "Active/Inactive User" flag than a "currently-logged-in" flag, which is more what I'm looking for.
Before I screw thing up too badly by modifying core OX/XP functionality, I wanted to see if anyone on the group here has addressed this before and, if so, what techniques you might have used.
PS - I'm currently in a straight-forward, basic Tomcat model so want to stay within this model for now, so any suggestions should be within that context.
Thanks in advance as always!
Hi Gerry,
I cannot help you, as I never had contact with XavaPro, but I would like to ask you, how can you identify that the user is logged already or not?
Let's say that I logged in as "admin" and suddenly after that I lost my internet connection. For the server I am logged now. Then I go to another computer with a working connection and try to login. Will the server block me, because I just logged in in another machine?
Did you think about it already? I would really want to know if people faced this question already, and if they managed to solve it. Thanks!
Carlson,
First, it should not matter whether it's OX or XP (I think...)
Second, as it exists, there is an internal activity timer that will automatically log a user out after X seconds of inactivity. Even outside that context, an administrator can reset the logged-in state of a disconnected user, though that should be a very rare occasion.
So the solution would be something like this:
You need to create a new class to replace SignInHelper. The method isAuthorized will check for the lastActivity field. If the lastActive was more than X seconds/minutes ago, and the user and password matches, it returns true, otherwise, false;
You need to create a new action, let's call it activityAction on the parent of all application's controller (Typical, MyTypical controller, name it). This action will execute before-each-request;
This action will update the lastActivity field of the user on the database with the actual time;
You create an action for the user to reset the last activity
For the second step, instead of using the database, I think it could be better to use the session object, maybe it is better for the performance?
I hope I could help you!
Thanks, Carlson- great info! I'll keep the list posted on progress.
Carlson, in looking into the files, it appears that there is an exposed "count" method in the User class, which does not seem to be referenced elsewhere (that I have found so far :-) ).
In olden times, that was a fairly standard way of tracking. I.e. when User logs in, check count. If count > 0 fail login with "already logged in User" message. On logout, decrement count (or set to zero - I still think in device driver mode sometimes...).
Would that be practical and/or am I missing someting else?
Thanks again!
Hi Gerry, I never saw something related to a "count" into the code... but I don't think that having a counter incresed/decresed by the login/logout user process should be enough for your goal... I could mention some drawback about this approach, here are somes: what when the user session get timed out?, or what when the user just close the browser?.. as you can figure out, the session destroyed process can be fired without your control. Anyway, at the end, there are several ways to implement what you want... without persist any data related.
So, here is one:
Create a class (maybe in your * .listeners package) that implements HttpSessionListener interface:
You should be tempted to add your increment logic to the sessionCreated method of the session listener, but believe me... it is better to increment in the login process to make sure the user is really loged in. Also, the sessionCreated method is sometimes called even when the user has not loged in. So, we use the listener to decrease only, because that way we will cover any manual or automatic logout.
Btw, take care about Users.getCurrent()... I have found some situations where it resturn null (meaning no user loged in), even when there was at least one user loged in.
Add an entry to your listeners.xml file, just add the file if you don't have it in your project yet, just next to your web.xml (why not directly to your web.xml?, well... check the wiki about that):
Remember you need to run updateOX Ant task from build.xml... to recreate your web.xml.
What now?.. well, some advice for your session counter:
Create a thread safe Singleton (pattern) class to handle your concurrent session count... little example:
Then you use the Singleton in your HttpSessionListener's sessionDestroyed method to decrement the session counter by user.
Go to your login process and add code to use the singleton for increment the corresponding session by the user loged in. It could be done in the SignInAction plugin acction (once the user has been validated)... you should be better use the User object (created in the login process) and user.getName() here (instead Users.getCurrent()), because I think Users.getCurrent() will return null at this stage.
Finally, in the same process login (at the begining), you can add a check to see if you allow the coming login to be allowed to continue or will be rejected because "N concurrent session allowed only".
So, I have not tested all that... but seems to work.
Just try and then let me know how you going.
Going beyond your original requirement, you could have a number property in your global app Preference module (or .properties) that define how many concurrent session for the same user you want to allow.
Regards,
Last edit: Hayrol Reyes 2016-04-30
Thanks, Hayrol! You are right, of course, so let me try your approach...
Gerry
Hi,
What do you thing about adding that feature as an built-in option in future XavaPro releases?
Hi,
Preventing the user log in more than once is not a lightly task, there are
several reasons on why it is not easy to safely implement it. Sometimes you
must prevent user automatic log out, as a matter of fact, this is a common
practice for non critical applications, basically as long as a user has a
browser opened the session will remain active. That is why besides 'truly'
know if the user is logged in, some sort of remote log out should be
implemented. Why? Imagine that you user logged in his computer at home left
the session opened. If the session timeout is short, there is no problem,
but if no, you get the idea.
It is a good idea, though.
Federico
On Mon, May 2, 2016 at 8:03 AM, Javier Paniza javierpaniza@users.sf.net
wrote:
Personally, I think it would be a great feature to have in XavaPro.
There have always been issues with users failing to log out, connections broken, etc., but the benefits - to me - outweigh the those issues. Basically, of course, it enforces the ability of the app to verify that ThisUser performed ThisOperation, and no one else.
Hi friends,
Finally this feature is implemented in XavaPro and it will available for v7.3, in April 2024, just the next month.
How we solved the problem of other opened sessions? We take a simple approach, when a user logins his other sessions are invalidated. So we don't have the problem when the user closes the browser without clicking in logout.