web-dev-qa-db-ja.com

spring-boot redis:ユーザーのすべてのセッションを無効にする方法は?

Redisは初めてです。このチュートリアルに従って、RedisでHttpSessionを使用しました。

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

現在、私のアプリケーションには「すべてのデバイスからログアウト」オプションがあります。それをクリックすると、そのユーザーのすべてのセッションを削除または無効にするにはどうすればよいですか?

また、ユーザーがパスワードを変更した場合、現在のセッション以外のすべてのセッションを無効にするにはどうすればよいですか?

編集:

セッションレジストリを使ってみました。

_@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 dbで確認できます。

_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"
_

上記の2つのコマンドをコピーして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>
_
14
HeisenBerg

ユーザーセッションを無効にするための_you are following the correct path_であることをお知らせします

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

注意すべきこと

_SessionInformation.expireNow()
_

redisデータベースからエントリを削除することを意味するのではなく、あなたが正しく述べたように、セッションに期限切れの属性を追加するだけです。

しかし、これがどのようにユーザーのセッションを無効にするのですか?

ConcurrentSessionFilter が登場し、.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);
}
_

乾杯!

7
Mr.Arjun

これを削除キー「redisTemplate.opsForValue()。getOperations()。delete(KEY);」に試してください。

0
Radhey Shyam

これを試して

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

デバッグプロセスで一度だけ行いたい場合は、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>
0
ozooxo