spring-boot redis:如何使用户的所有会话无效?

我是redis的新手。 我已经按照本教程使用了redis的HttpSession。

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

现在我的应用程序已“退出所有设备”选项。 单击该按钮时,如何删除或使该用户的所有会话无效?

此外,当用户更改其密码时,如何使除当前会话之外的所有会话无效?

编辑:

我尝试使用Session Registry。

@Autowired private FindByIndexNameSessionRepository sessionRepository; @Autowired FindByIndexNameSessionRepository sessions; @RequestMapping(value = "/logoutalldevices", method = RequestMethod.GET) public Response test(HttpServletRequest request, HttpServletResponse response) throws Exception { SpringSessionBackedSessionRegistry sessionRegistry = new SpringSessionBackedSessionRegistry(sessionRepository); Collection 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(); } 

但它不是从redis db中删除会话或使其无效。 虽然它在名为’sessionAttr:org.springframework.session.security.SpringSessionBackedSessionInformation.EXPIRED’的会话中添加了一个新属性,其值为true。 我可以使用redis客户端在redis db中看到这个新的键值对

HGETALL 'sessionid'

编辑

我尝试使用redistemplate从redis db手动删除会话。

 @Autowired RedisTemplate redisTemplate; --------- redisTemplate.delete("spring:session:sessions:" + sessionId); redisTemplate.delete("spring:session:sessions:expires:" + sessionId); 

这几乎可行。 它从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> 

除了lastAccessedTime时,它删除了会话中的所有其他键值对。

还有一个奇怪的是,这是我在执行redisTemplate.delete("key")时在redis监视器中看到的日志:

 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" 

如果我将上述两个命令复制并粘贴到redis-client并执行,则删除密钥。 当我执行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> 

我想知道您you are following the correct path使用户会话无效的you are following the correct path

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

有些事要注意

 SessionInformation.expireNow() 

并不意味着从redis数据库中删除条目,它只是将您过期的属性附加到会话中,正如您正确提到的那样。

但是这会如何使用户的会话无效?

这里有ConcurrentSessionFilter ,其中.doFilter()方法可以automatically logging out

这是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); } 

干杯!

尝试使用删除键“redisTemplate.opsForValue()。getOperations()。delete(KEY);”

试试这个

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