1

So, the scenario is : User A logs in and working in the system with credentials X. User B, who is also a friend of A, want to log in using same credentials. As per the requirement, we are showing an alert saying some user is already logged in with same id and you want to continue by killing that session.

If the User B agrees, we need to kick the User A out of system. Now, what I would like to achieve is, once that killSession() method(in Spring Controller) is called, I have to send a push notification to the browser client of User A and log him out of the system.

I don't want to achieve this by setTimeout kinda stuff. I would like to trigger it from Server, so it doesn't create lot of HTTP requests to know if his session is alive or not.

Can you guys please help me what framework or lib I use to achieve this. I am a little new to this, and all I did was tried SockJS and Socket.IO but without any success because of my lack of understanding on how to do this. Appreciate any help guys!!

Rajkumar
  • 440
  • 7
  • 31
  • Can't we use old session.invalidate() method on the unique session ID of user A? – Abhinab Kanrar Jan 14 '16 at 05:40
  • @AbhinabKanrar I don't think you understand. We can kill session that way, but I would like to send a notification to User A's client side,so that it can start invalidate the session. – Rajkumar Jan 14 '16 at 05:44
  • Are you inventing this by yourself or are you using Spring Security? As that supports all of this out-of-the-box. – M. Deinum Jan 14 '16 at 06:49
  • I'm doing this by myself since spring security was rejected by the client. So I had to do this by trial and error and this is where I end up now! – Rajkumar Jan 14 '16 at 06:50

2 Answers2

1

We also faced a similar kind of problem, to resolve it we stored tomcat session in redis. Configuration required in tomcat context.xml

<!-- Default set of monitored resources -->
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" />
<Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager"
     host="172.16.1.167"
     port="6379"
     database="0"
     maxInactiveInterval="1440"
     sessionPersistPolicies="ALWAYS_SAVE_AFTER_REQUEST"/>

And in your code you can delete the session as

LOGGER.info("Invalidating previous session for agent: " + agentId);
String sessionId = null;
if (cacheService.getValue(agentId + "_session") != null)
  sessionId = (String) cacheService.getValue(agentId + "_session");
cacheService.deleteValue(agentId + "_session");
cacheService.deleteValue(sessionId + "_session");
if (cacheService.getValue(sessionId) != null) {
  LOGGER.info("Session invalidated from redis for agent: " + agentId);
  cacheService.deleteValue(sessionId);
} else {
  LOGGER.info("Agent session not found in redis sessions for agent: " + agentId);
}

where cacheService is nothing but Redis Template. after this you can push a message using faye.

 URL url = new URL("http://172.16.213.158:81/<your-data>);
  InputStream inputStream = url.openStream();
  BufferedReader rd = new BufferedReader(new InputStreamReader(inputStream));
  rd.readLine();
  rd.close();

where 172.16.213.158:81 is node server

Pulkit
  • 3,953
  • 6
  • 31
  • 55
  • As much as I loved your idea, but the big issues with the client was not to use Redis or any kinda disk store! So it is not possible to do. How about Atmosphere? Can we do with it? – Rajkumar Jan 14 '16 at 06:26
  • if I am not wrong atmosphere is same as of faye. you can use anything. If you dont want to use redis its ok , just delete the jsessionId from tomcat server for that user. – Pulkit Jan 14 '16 at 06:30
  • I feel dumb to ask this, but may I know what do you mean by delete the jsessionId from tomcat?(Never done it before) And if you know it already, can you tell me how to do that? it sounds simple. – Rajkumar Jan 14 '16 at 06:46
  • this will help you http://stackoverflow.com/questions/3092363/how-can-i-load-java-httpsession-from-jsessionid/3092495#3092495 – Pulkit Jan 14 '16 at 07:39
  • About the link you posted above this comment, how it will work in clustered environment? Is it possible to share the sessions between servers? – Rajkumar Jan 22 '16 at 12:25
  • Yes, you can use redis for that, so instead of storing session in tomcat, it will be stored in redis for central access. – Pulkit Jan 22 '16 at 13:20
  • 1
    Well, I used DB, since redis wasn't allowed. Anyway, I accepted your answer because that is the closest one for my problem! Thanks for the help. – Rajkumar Jan 22 '16 at 21:30
  • Thats great but still consider it again because db wont help you in scaling large traffic. – Pulkit Jan 23 '16 at 09:50
  • 1
    Thanks for the concern, but there was nothing I can do about that! Because of the fact that it uses RAM to manipulate data rather than disk. But still I'm looking into MongoDB to see that can fit in this use case. – Rajkumar Jan 25 '16 at 04:55
1

Take one extra field in User Object, for example isLoggedIn as boolean field and set it to true until the user is logged in. As soon as user logs out set it to false. This need to be done for session expiry time also. As soon as the session expires this field should be set to false automatically using triggers or through Stored Procedure call. Then, in the Login Controller, you can simply add a little more logic, which will check if there is a session with User A, ask a question for User B and do your stuff. Hope that helps.

m.aibin
  • 3,528
  • 4
  • 28
  • 47
  • Thanks for the reply.Let's say if we have trigger, which monitors the USER_SESSION_HISTORY table and once User B agrees to kill session, we will update some value in this table. Now how does the User A's connection knows to log out of the system, is my question. It's not about how I am going to invalidate my session, but how I am going to achieve it without doing it by setInterval or setTimeout. – Rajkumar Jan 14 '16 at 06:29
  • My first thought is that you can have a Spring scheduler running each few minutes and checks this values in DB. But with many users (over 10000) this could be a little too heavy process. – m.aibin Jan 14 '16 at 06:32
  • That was the first suggestion I get from friends, but I wouldn't do that. Schedulers are not meant to do this and we have tools to achieve this. So I just started searching and now I am here for help! :) – Rajkumar Jan 14 '16 at 07:02