web-dev-qa-db-de.com

spring-boot redis: Wie werden alle Sitzungen eines Benutzers ungültig?

Ich bin neu bei Redis. Ich bin diesem Tutorial gefolgt, um HttpSession mit redis zu verwenden.

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

Jetzt hat meine Anwendung die Option 'Abmelden von allen Geräten'. Wenn darauf geklickt wird, wie kann ich alle Sitzungen dieses Benutzers entfernen oder ungültig machen? 

Wie kann ich auch alle seine Sitzungen außer der aktuellen Sitzung für ungültig erklären, wenn der Benutzer sein Kennwort ändert?

Bearbeiten: 

Ich habe versucht, die Sitzungsregistrierung zu verwenden.

@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();
}

Die Sitzung wird jedoch nicht aus redis db entfernt oder ungültig gemacht. Sie fügt der Sitzung jedoch ein neues Attribut mit dem Namen 'sessionAttr: org.springframework.session.security.SpringSessionBackedSessionInformation.EXPIRED' mit dem Wert true hinzu. Ich kann dieses neue Schlüsselwertpaar in redis db mit redis client sehen, wenn ich dies tue 

HGETALL 'sessionid'

Bearbeiten

Ich habe versucht, die Sitzung mit redistemplate manuell aus redis db zu löschen.

@Autowired
RedisTemplate<String, String> redisTemplate;

---------

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

Das funktioniert fast. Der Wert wird aus redis db gelöscht, nicht jedoch der Schlüssel. 

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> 

Es löschte alle anderen Schlüsselwertpaare innerhalb der Sitzung mit Ausnahme der lastAccessedTime-Zeit.

Eine seltsame Sache ist, das ist das Protokoll, das ich in redis monitor sehe, wenn redisTemplate.delete("key") ausgeführt wird:

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"

Wenn ich die beiden obigen Befehle kopiere und einfügte, um ihn erneut auszuführen und auszuführen, werden die Schlüssel gelöscht. Ich sehe keine Schlüssel mehr, wenn ich keys * mehr ausführe. Ich frage mich, warum der Schlüssel nicht gelöscht wird, wenn er mit RedisTemplate gelöscht wird.

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

Ich würde Sie gerne wissen, dass you are following the correct path für das Ungültigmachen der Benutzersitzungen

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

Etwas zu beachten

SessionInformation.expireNow()

bedeutet nicht, Einträge aus der redis-Datenbank zu entfernen, sondern fügt das abgelaufene Attribut einfach an die Sitzung an.

Wie wird die Sitzung des Benutzers jedoch ungültig?

Hier kommt die ConcurrentSessionFilter ins Spiel, wobei die .doFilter()-Methode den Trick von automatically logging out ausführt

Hier ist der Ausschnitt für 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);
}

Prost!

5
Mr.Arjun

Versuchen Sie dies mit dem Löschschlüssel "redisTemplate.opsForValue (). GetOperations (). Delete (KEY);"

0
Radhey Shyam

Versuche dies

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

Wenn Sie beim Debuggen nur eine einzige Aktion ausführen möchten, müssen Sie sich nur bei redis_cli Anmelden und alle Redis-Tasten leeren.

$ 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>
0
ozooxo