web-dev-qa-db-fra.com

spring-boot redis: Comment invalider toutes les sessions d'un utilisateur?

Je suis nouveau à Redis. J'ai suivi ce tutoriel pour utiliser HttpSession avec Redis.

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

Maintenant, mon application dispose de l'option "Déconnexion de tous les périphériques". Quand on clique dessus, comment puis-je supprimer ou invalider toutes les sessions de cet utilisateur? 

De même, lorsque l'utilisateur modifie son mot de passe, comment puis-je invalider toutes ses sessions, à l'exception de la session en cours?

Modifier: 

J'ai essayé d'utiliser 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();
}

Mais il ne s'agit pas de supprimer la session de la base de données redis ni de l'invalider. bien que cela ajoute un nouvel attribut à la session nommé 'sessionAttr: org.springframework.session.security.SpringSessionBackedSessionInformation.EXPIRED' avec la valeur true. Je peux voir cette nouvelle paire de valeurs de clé dans Redis DB en utilisant le client Redis quand je fais 

HGETALL 'sessionid'

Modifier

J'ai essayé de supprimer la session manuellement de Redis DB en utilisant Redistemplate.

@Autowired
RedisTemplate<String, String> redisTemplate;

---------

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

Cela fonctionne presque. Il supprime la valeur de la base de données redis, mais pas la clé. 

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> 

Il a supprimé toutes les autres paires de valeurs de clé de la session, à l'exception de l'heure lastAccessedTime.

Aussi étrange que cela soit, c’est le journal que je vois dans le moniteur Redis lorsque redisTemplate.delete("key") est exécuté:

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"

Si je copie et colle les deux commandes ci-dessus dans redis-client et que je les exécute, les clés sont supprimées. Je ne vois plus les clés quand j'exécute keys *. Je me demande pourquoi la clé n'est pas supprimée lorsqu'elle est supprimée à l'aide de 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>
12
HeisenBerg

Je voudrais savoir que you are following the correct path pour invalider les sessions utilisateur

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

Somethings à noter

SessionInformation.expireNow()

n'est pas censé supprimer des entrées de la base de données redis, il ajoute simplement l'attribut expiré à la session comme vous l'avez mentionné à juste titre.

Mais comment cela invalide la session de l'utilisateur?

Voici le ConcurrentSessionFilter en jeu où la méthode .doFilter() fait le tour de automatically logging out

Voici l'extrait de code pour 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);
}

Trinquons à ça!

5
Mr.Arjun

Essayez ceci pour la clé de suppression "redisTemplate.opsForValue (). GetOperations (). Delete (KEY);"

0
Radhey Shyam

Essaye ça

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