2017-03-29 1 views
10

Je suis nouveau à redis. J'ai suivi ce tutoriel pour utiliser HttpSession avec redis.spring-boot redis: Comment invalider toutes les sessions d'un utilisateur?

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

Maintenant ma demande "Déconnexion de tous les appareils de l'option. Lorsque cela est cliqué, comment puis-je supprimer ou invalider toutes les sessions de cet utilisateur?

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

Edit:

J'essayé d'utiliser la session d'enregistrement. Mais il ne supprime pas la session de redis db ou ne l'invalide pas. mais ajoute un nouvel attribut à la session nommée 'sessionAttr: org.springframework.session.security.SpringSessionBackedSessionInformation.EXPIRED' avec la valeur true. Je peux voir cette nouvelle valeur paire de clés dans Redis db à l'aide Redis client lorsque je

HGETALL 'sessionid'

Modifier

J'ai essayé de supprimer la session manuellement à partir 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 redis db, 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> 

Elle a supprimé toutes les autres valeurs clés paires à l'intérieur de la session, sauf le temps lastAccessedTime.

aussi un étrange c'est, c'est le journal que je vois dans le moniteur de Redis quand 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 copier et coller les deux commandes ci-dessus pour Redis-client et d'exécuter, les clés sont supprimé Je ne vois plus les touches lorsque j'exécute keys * plus. Je me demande pourquoi la clé ne se supprimé lorsque son supprimé à l'aide 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> 
+0

pouvez-vous partager votre configuration de sécurité de printemps? –

+0

Je n'ai défini aucune configuration. Ajout de la dépendance à la sécurité spring-boot-starter. C'est tout. Ai-je besoin d'ajouter quelque chose? – HeisenBerg

+0

vous avez commenté '// sessionRegistry.removeSessionInformation (sessionId);' cela devrait fonctionner correctement. Qu'est-ce qui s'est passé dans votre cas? –

Répondre

4

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

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

Somethings à noter

SessionInformation.expireNow() 

est signifie pas pour supprimer les entrées de la base de données redis, il ajoute juste l'attribut expiré à la session comme vous l'avez mentionné à juste titre.

Mais comment cela invalide la session de l'utilisateur?

vient ici 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); 
} 

Bravo à ça!

+0

Un problème que je trouve avec cette approche est que les sessions expirées ne sont jamais supprimées de redis db. – HeisenBerg

0

Essayez ceci pour la clé de suppression "redisTemplate.opsForValue() getOperations() supprimer (KEY).".

+0

Cela a le même effet. Ne supprime pas la clé. – HeisenBerg