spring-boot redis : How to invalidate all sessions of a user?

Multi tool use
Multi tool use


spring-boot redis : How to invalidate all sessions of a user?



I'm new to redis. I've followed this tutorial to use HttpSession with redis.



https://docs.spring.io/spring-session/docs/current/reference/html5/guides/boot.html



Now my application has 'Sign out from all devices' option. When that is clicked how do I remove or invalidate all sessions of that user?



Also when the user changes his password, how do I invalidate all his sessions except the current session?



Edit:



I tried using Session Registry.


@Autowired
private FindByIndexNameSessionRepository sessionRepository;

@Autowired
FindByIndexNameSessionRepository<? extends ExpiringSession> sessions;

@RequestMapping(value = "/logoutalldevices", method = RequestMethod.GET)
public Response test(HttpServletRequest request, HttpServletResponse response) throws Exception {

SpringSessionBackedSessionRegistry sessionRegistry = new SpringSessionBackedSessionRegistry(sessionRepository);

Collection<? extends ExpiringSession> usersSessions = sessions
.findByIndexNameAndIndexValue(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, "myUserId")
.values();

usersSessions.forEach((temp) -> {
String sessionId = temp.getId();
// sessionRegistry.removeSessionInformation(sessionId);
SessionInformation info = sessionRegistry.getSessionInformation(sessionId);
info.expireNow();
});

return Response.ok().build();
}



But it is not removing the session from redis db or invalidating it. though it's adding a new attribute to the session named 'sessionAttr:org.springframework.session.security.SpringSessionBackedSessionInformation.EXPIRED' with value true. I can see this new key value pair in redis db using redis client when I do



HGETALL 'sessionid'


HGETALL 'sessionid'



Edit



I tried deleting the session manually from redis db using redistemplate.


@Autowired
RedisTemplate<String, String> redisTemplate;

---------

redisTemplate.delete("spring:session:sessions:" + sessionId);
redisTemplate.delete("spring:session:sessions:expires:" + sessionId);



This almost works. It deletes the value from redis db, but not the key.


127.0.0.1:6379> keys *
1) "spring:session:sessions:25635a14-a4f1-4aa1-bf5a-bc20f972eec7"
2) "spring:session:sessions:expires:25635a14-a4f1-4aa1-bf5a-bc20f972eec7"
3) "spring:session:index:org.springframework.session.FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME:1"
127.0.0.1:6379> hgetall spring:session:sessions:25635a14-a4f1-4aa1-bf5a-bc20f972eec7
1) "lastAccessedTime"
2) "xacxedx00x05srx00x0ejava.lang.Long;x8bxe4x90xccx8f#xdfx02x00x01Jx00x05valuexrx00x10java.lang.Numberx86xacx95x1dx0bx94xe0x8bx02x00x00xpx00x00x01[R'x15xc1"
127.0.0.1:6379>



It deleted all other key values pairs inside the session except lastAccessedTime time.



Also one weird this is, this is the log I see in redis monitor when redisTemplate.delete("key") is executed:


redisTemplate.delete("key")


1491731944.899711 [0 127.0.0.1:62816] "DEL" "spring:session:sessions:25635a14-a4f1-4aa1-bf5a-bc20f972eec7"
1491731944.899853 [0 127.0.0.1:62816] "DEL" "spring:session:sessions:expires:25635a14-a4f1-4aa1-bf5a-bc20f972eec7"



If I copy and paste the above two commands to redis-client and execute, the keys are deleted. I do not see keys when I execute keys * anymore. I wonder why the key is not getting deleted when its deleted using RedisTemplate


keys *


RedisTemplate


127.0.0.1:6379> "DEL" "spring:session:sessions:25635a14-a4f1-4aa1-bf5a-bc20f972eec7"
(integer) 1
127.0.0.1:6379> "DEL" "spring:session:sessions:expires:25635a14-a4f1-4aa1-bf5a-bc20f972eec7"
(integer) 1
127.0.0.1:6379> keys *
1) "spring:session:index:org.springframework.session.FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME:1"
127.0.0.1:6379>





can you share your spring security configuration?
– Mr.Arjun
Apr 10 '17 at 11:20





I haven't set any configuration. Just added spring-boot-starter-security dependency. That's it. Do I need to add something?
– HeisenBerg
Apr 10 '17 at 11:22





you commented // sessionRegistry.removeSessionInformation(sessionId); that should work fine. What happened in your case?
– Mr.Arjun
Apr 12 '17 at 6:43


// sessionRegistry.removeSessionInformation(sessionId);





I tried it, that didn't work.
– HeisenBerg
Apr 12 '17 at 7:09





Would the sessionStatus.setComplete() work for your case?
– Rock
Apr 12 '17 at 7:45


sessionStatus.setComplete()




3 Answers
3



I would like to know you that you are following the correct path for invalidating the user sessions


you are following the correct path


usersSessions.forEach((session) -> {
sessionRegistry.getSessionInformation(session.getId()).expireNow();
});



Somethings to note


SessionInformation.expireNow()



is not mean to remove entries from the redis database, it just appends the expired attribute to session as you rightly mentioned.


redis



But how this invalidates the session of the user?



Here comes the ConcurrentSessionFilter into play where
.doFilter() method does the trick of automatically logging out


.doFilter()


automatically logging out



Here is the snippet for ConcurrentSessionFilter


public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;

HttpSession session = request.getSession(false);

if (session != null) {
SessionInformation info = sessionRegistry.getSessionInformation(session
.getId());

if (info != null) {
if (info.isExpired()) {
// Expired - abort processing
doLogout(request, response);

String targetUrl = determineExpiredUrl(request, info);

if (targetUrl != null) {
redirectStrategy.sendRedirect(request, response, targetUrl);

return;
}
else {
response.getWriter().print(
"This session has been expired (possibly due to multiple concurrent "
+ "logins being attempted as the same user).");
response.flushBuffer();
}

return;
}
else {
// Non-expired - update last request date/time
sessionRegistry.refreshLastRequest(info.getSessionId());
}
}
}

chain.doFilter(request, response);
}



Cheers to that!





One issue I find with this approach is that the expired sessions are never removed from redis db.
– HeisenBerg
Jun 29 '17 at 6:56





@HeisenBerg there you go: spring.session.cleanup.cron.expression (system property)
– Ursache
Apr 3 at 10:49




Try this for delete key "redisTemplate.opsForValue().getOperations().delete(KEY);"





It has the same effect. Doesn't delete the key.
– HeisenBerg
Apr 10 '17 at 7:17



Try this


usersSessions.forEach((session) -> {
sessionRegistry.delete(session.getId());
});






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

3F9wUcUw9qaOTjz,p1RuMc a4Al1DNmlF4T7HdAOJv7
sDVzqMbIwinu 6u

Popular posts from this blog

PHP contact form sending but not receiving emails

Do graphics cards have individual ID by which single devices can be distinguished?

Create weekly swift ios local notifications