spring-boot redis:如何使用户的所有会话无效? [英] spring-boot redis : How to invalidate all sessions of a user?

查看:128
本文介绍了spring-boot redis:如何使用户的所有会话无效?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Redis的新手.我已经按照本教程将HttpSession与Redis结合使用.

I'm new to redis. I've followed this tutorial to use HttpSession with redis.

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

现在,我的应用程序具有从所有设备注销"选项.单击该按钮后,如何删除该用户的所有会话或使该用户的所有会话无效?

Now my application has 'Sign out from all devices' option. When that is clicked how do I remove or invalidate all sessions of that user?

此外,当用户更改密码时,如何使除当前会话之外的所有会话无效?

Also when the user changes his password, how do I invalidate all his sessions except the current session?

我尝试使用会话注册表.

I tried using 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的新属性.

But it is not removing the session from redis db or invalidating it. though it's adding a new attribute to the session named 'sessionAttr:org.springframework.session.security.SpringSessionBackedSessionInformation.EXPIRED' with value true. I can see this new key value pair in redis db using redis client when I do

HGETALL 'sessionid'

修改

我尝试使用redistemplate从redis数据库中手动删除会话.

I tried deleting the session manually from redis db using redistemplate.

@Autowired
RedisTemplate<String, String> redisTemplate;

---------

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

这几乎可行.它从redis db中删除值,但不删除密钥.

This almost works. It deletes the value from redis db, but not the key.

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时间以外的所有其他键值对.

It deleted all other key values pairs inside the session except lastAccessedTime time.

这也很奇怪,这是我在执行redisTemplate.delete("key")时在redis监视器中看到的日志:

Also one weird this is, this is the log I see in redis monitor when redisTemplate.delete("key") is executed:

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

If I copy and paste the above two commands to redis-client and execute, the keys are deleted. I do not see keys when I execute keys * anymore. I wonder why the key is not getting deleted when its deleted using 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>

推荐答案

我想知道, you are following the correct path 使用户会话无效

I would like to know you that you are following the correct path for invalidating the user sessions

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

注意事项

SessionInformation.expireNow()

并不意味着从redis数据库中删除条目,它只是将您已正确提及的过期属性附加到会话上.

is not mean to remove entries from the redis database, it just appends the expired attribute to session as you rightly mentioned.

但是这如何使用户会话无效?

这是

Here comes the ConcurrentSessionFilter into play where .doFilter() method does the trick of 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);
}

为此加油!

这篇关于spring-boot redis:如何使用户的所有会话无效?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆