当用户注销时,Spring Security从数据库中删除会话

时间:2020-07-26 19:35:48

标签: spring spring-boot spring-security spring-session

我正在我的项目中实现Spring Security,并使用mysql数据库存储会话。一切正常,但是当用户注销时,它的会话也会从我不想要的数据库中删除。我只希望会话无效,但不希望从数据库中删除会话。 在调试时,我发现:

    public void logout(HttpServletRequest request, HttpServletResponse response,
        Authentication authentication) {
    Assert.notNull(request, "HttpServletRequest required");
    if (invalidateHttpSession) {
        HttpSession session = request.getSession(false);
        if (session != null) {
            logger.debug("Invalidating session: " + session.getId());
            **session.invalidate();**
        }
    }

    if (clearAuthentication) {
        SecurityContext context = SecurityContextHolder.getContext();
        context.setAuthentication(null);
    }

    SecurityContextHolder.clearContext();
}

此代码来自SecurityContextLogoutHandler类。

进一步,代码执行进入:

    private final class HttpSessionWrapper extends HttpSessionAdapter<S> {

        HttpSessionWrapper(S session, ServletContext servletContext) {
            super(session, servletContext);
        }

        @Override
        public void invalidate() {
            super.invalidate();
            SessionRepositoryRequestWrapper.this.requestedSessionInvalidated = true;
            setCurrentSession(null);
            clearRequestedSessionCache();
            **SessionRepositoryFilter.this.sessionRepository.deleteById(getId());**
        }

    }

函数的最后一行删除我不需要的会话。

我的问题是,当用户注销时,我可以阻止Spring Security从数据库中删除会话吗?或者这是Spring Security的工作方式?

1 个答案:

答案 0 :(得分:2)

用户注销后,您是否有任何特定原因不希望从数据库中删除会话?这是很常见的行为。会话代表您已登录的客户端。客户端登录后(例如,提供有效的凭据,带有用户名的密码),将创建会话ID并将其发送给客户端。该会话ID代表有效的登录连接。在此客户端发出的后续请求中,他只会在标头中发送此会话ID,您的应用将检查此会话ID是否存储在有效会话的内部(例如您的数据库),并且是否已将此请求视为已验证(因此客户端未必须发送他的凭据,每个请求都必须验证该凭据,他仅发送会话ID)。客户端注销后,会话ID将无效,因为注销后,其连接将不再通过身份验证。因此,是的,这就是Spring安全性的工作方式,不需要持久化无效的会话。您还必须实现用于从数据库清除会话的自定义机制(如果在用户注销时未清除会话,则将清除会话)。另外,您可能会考虑在内存中使用会话池而不是数据库。

编辑:在数据库会话池的情况下,我不知道弹簧检查的有效会话如何,但是在某些时候它必须访问数据库读取所有会话,因此它可以找出哪个会话ID是有效的(我想这是对每个会话都完成的)之后-至少登录请求)。如果该会话同时定义了有效会话,那么如何将无效会话保留在数据库会话池中?