当前位置: 首页 > 面试题库 >

spring-boot redis:如何使用户的所有会话无效?

南宫建白
2023-03-14
问题内容

我是Redis的新手。我已经按照本教程将HttpSession与redis一起使用。

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
client在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"

如果我将以上两个命令复制并粘贴到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>

问题答案:

我想知道你是 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);
}

为此加油!



 类似资料:
  • 我正在使用Spring Boot、Spring Security性和spring会话(redis)构建spring REST web应用程序。我正在使用SpringCloud和zuul代理按照网关模式构建一个云应用程序。在这个模式中,我使用spring会话来管理redis中的HttpSession,并使用它来授权我的资源服务器上的请求。当执行更改会话权限的操作时,我希望更新该对象,以便用户不必注销

  • 问题内容: 我在iOS应用中使用Firebase身份验证。当用户使用Firebase登录我的应用程序然后注销该用户的所有其他设备(会话)时,Firebase中是否有任何方法?我可以使用Firebase admin SDK来做到这一点吗? 问题答案: 当我遇到此问题时,我已使用云功能解决了该问题,请访问此链接以获取更多详细信息https://firebase.google.com/docs/auth

  • 问题内容: 我正在使用Spring Security构建一个Web应用程序,该应用程序将驻留在Amazon EC2上并使用Amazon的Elastic Load Balancer。不幸的是,ELB不支持粘性会话,因此我需要确保我的应用程序无需会话即可正常运行。 到目前为止,我已经设置了RememberMeServices来通过cookie分配令牌,并且可以正常工作,但是我希望cookie在浏览器会

  • 我已经使用Spring Security两周了,除了匿名用户和会话超时之外,它工作得很好。 用例#1 null 如果他们的会话超时,将显示invalidSessionUrl页面,并指示用户登录。 我已经阅读了大量的SO和博客文章,但我似乎找不到用例1的解决方案。我使用的是Spring4.1.6.RELEASE、Spring Security 4.0.2 RELEASE和Tomcat8。 下面是我的

  • 问题内容: 我正在将JSF 1.2与Richfaces和Facelets结合使用。 我有一个包含许多会话范围的bean和一些应用程序bean的应用程序。 假设用户使用Firefox登录。使用ID =“ A”创建会话;然后,他打开Chrome并使用相同的凭据再次登录。使用ID =“ B”创建一个会话。 创建会话“ B”时,我希望能够销毁会话“ A”。怎么做? 也。当Firefox中的用户执行任何操作

  • 我正在使用和开发一个web应用程序。我正在使用Active Directory作为用户联邦来检索所有用户信息。 但是要在我的web应用程序中使用这些信息,我认为我必须将它们保存在“local-webapp”数据库中。 那么在用户被记录之后,我如何将他们保存在我的数据库中呢? 客户: 错误是: 我哪里做错了? 编辑6 这是启用日志记录后的日志表单密钥斗篷: