Spring -boot redis: как аннулировать все сеансы пользователя?
Я новичок в redis. Я следил за этим руководством, чтобы использовать HttpSession с redis.
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 db, используя redis client, когда я делаю
HGETALL 'sessionid'
Edit
Я попытался удалить сеанс вручную из redis db, используя redistemplate.
@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>
Он удалил все остальные пары значений ключей внутри сеанса, кроме последнего времениAccessedTime.
Кроме того, это странно, это журнал, который я вижу на мониторе 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"
Если я скопирую и вставлю указанные выше две команды в 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>
Ответы
Ответ 1
Я хотел бы знать, что you are following the correct path
для аннулирования пользовательских сессий
usersSessions.forEach((session) -> {
sessionRegistry.getSessionInformation(session.getId()).expireNow();
});
Кое-что отметить
SessionInformation.expireNow()
не означает удаление записей из базы данных redis
, он просто добавляет атрибут expired к сессии, как вы правильно упомянули.
Но как это делает недействительным сеанс пользователя?
Здесь вступает в игру ConcurrentSessionFilter, где .doFilter()
выполняет .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);
}
Приветствия к этому!
Ответ 2
Попробуйте это для клавиши "redisTemplate.opsForValue(). getOperations(). delete (KEY);"
Ответ 3
Попробуй это
usersSessions.forEach((session) -> {
sessionRegistry.delete(session.getId());
});
Ответ 4
Если вы просто хотите сделать один раз в процессе отладки, вы можете просто войти в redis_cli
и 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>