java spring-boot redis:如何使用户的所有会话无效?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/43090679/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
spring-boot redis : How to invalidate all sessions of a user?
提问by Sarath Nagesh
I'm new to redis. I've followed this tutorial to use HttpSession with redis.
我是 redis 的新手。我已经按照本教程将 HttpSession 与 redis 一起使用。
https://docs.spring.io/spring-session/docs/current/reference/html5/guides/boot.html
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
但它不会从 redis db 中删除会话或使其无效。尽管它向名为“sessionAttr:org.springframework.session.security.SpringSessionBackedSessionInformation.EXPIRED”的会话添加了一个新属性,值为true。当我这样做时,我可以使用 redis 客户端在 redis db 中看到这个新的键值对
HGETALL 'sessionid'
HGETALL 'sessionid'
Edit
编辑
I tried deleting the session manually from redis db using redistemplate.
我尝试使用 redistemplate 从 redis db 手动删除会话。
@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.
这几乎有效。它从 redis db 中删除值,但不删除键。
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) "\xac\xed\x00\x05sr\x00\x0ejava.lang.Long;\x8b\xe4\x90\xcc\x8f#\xdf\x02\x00\x01J\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00xp\x00\x00\x01[R'\x15\xc1"
127.0.0.1:6379>
It deleted all other key values pairs inside the session except lastAccessedTime time.
它删除了会话中除 lastAccessedTime 时间之外的所有其他键值对。
Also one weird this is, this is the log I see in redis monitor when redisTemplate.delete("key")
is executed:
还有一个奇怪的是,这是我在 redis 监视器中看到的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
如果我把上面两个命令复制粘贴到redis-client执行,key就被删除了。当我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>
采纳答案by Mr.Arjun
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 ConcurrentSessionFilterinto play where
.doFilter()
method does the trick of automatically logging out
这是ConcurrentSessionFilter发挥作用的地方,
.doFilter()
方法是automatically logging out
Here is the snippet for ConcurrentSessionFilter
这是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!
为此干杯!
回答by Sagar U
Try this
试试这个
usersSessions.forEach((session) -> {
sessionRegistry.delete(session.getId());
});
回答by ozooxo
If you just want to do one time thing in debugging process, you can just log into redis_cli
and flush all Redis keys.
如果你只想在调试过程中做一次事情,你可以登录redis_cli
并刷新所有 Redis 键。
$ redis-cli
127.0.0.1:6379> KEYS *
1) "spring:session:index:org.springframework.session.FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME:bbb"
2) "spring:session:expirations:1558782600000"
3) "spring:session:expirations:1558783140000"
4) "spring:session:sessions:expires:953146bf-7300-4394-bbf0-bf606ff6b326"
5) "spring:session:expirations:1558782540000"
6) "spring:session:sessions:953146bf-7300-4394-bbf0-bf606ff6b326"
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> KEYS *
(empty list or set)
127.0.0.1:6379>
回答by Radhey Shyam
Try this for delete key "redisTemplate.opsForValue().getOperations().delete(KEY);"
试试这个删除键“redisTemplate.opsForValue().getOperations().delete(KEY);”