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

时间:2017-03-29 10:16:27

标签: java spring session 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<? 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();
}

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

HGETALL 'sessionid'

修改

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

@Autowired
RedisTemplate<String, String> 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>

6 个答案:

答案 0 :(得分:7)

我想知道 Metric hoursWorked = (Metric) ctx.getBean("hoursWorkedBean"); System.out.println(hoursWorked.getName()); // prints out "Untitled Metric", but should print out "hoursWorked" 会使用户会话无效

you are following the correct path

要注意的事项

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

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

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

这里有ConcurrentSessionFilter redis方法可以解决.doFilter()

的问题

以下是 ConcurrentSessionFilter

的摘要
automatically logging out

干杯!

答案 1 :(得分:2)

@Autowired
private RedisIndexedSessionRepository redisIndexedSessionRepository;

redisIndexedSessionRepository.findByPrincipalName('your@login').keySet().forEach(redisIndexedSessionRepository::deleteById);

答案 2 :(得分:0)

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

答案 3 :(得分:0)

尝试一下

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

答案 4 :(得分:0)

如果您只想在调试过程中做一件事,则只需登录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>

答案 5 :(得分:0)

我偶尔会遇到现有会话对象与当前代码不兼容的问题,通常是在升级到包含较新 Spring 版本的版本之后。即 serialVersionUID 已更改。

在这种情况下,您不能使用任何会话接口(以及上面的答案),因为它们都会尝试对无法完成的对象进行反序列化。

相反,你只是回到基础

Set<String> sessionKeys = redisTemplate.keys("spring:session:*");
if (sessionKeys != null) {
    redisTemplate.delete(sessionKeys);
}

如果您在 "spring:session:*" 上设置了不同的 redisNameSpace,关键字搜索 @EnableRedisHttpSession 将需要更改