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

Spring Security deletes session form the database when user logs out

我正在我的项目中实现 spring 安全性,并使用 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 class。

进一步,代码执行进入:

    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 安全性在用户注销时从数据库中删除会话吗?或者这就是 spring 安全性的工作原理?

您是否有任何特定原因不想在用户注销后从数据库中删除 session?这是非常常见的行为。 Session 代表您登录的客户端。客户端登录后(提供有效的凭据,例如带有用户名的密码)session ID 被创建并发送给客户端。此 session ID 代表有效的登录连接。在此客户的后续请求中,他只会在 header 中发送此 session ID,您的应用程序将检查此 session ID 是否存储在有效的 session 中(您的数据库例如),如果是,则此请求被视为已通过身份验证(因此客户端不必发送他的凭据,每个请求都必须对其进行验证,他只发送 session ID)。一旦客户端注销,session ID 就会失效,因为注销后他的连接不再经过身份验证。因此,是的,这就是 spring 安全工作的方式,没有必要坚持无效的 session。您还必须实施自定义机制以从数据库中清除 session(如果不是在用户注销时,则何时清除 session)。您也可以考虑在内存中使用 session 池而不是 DB。

编辑:我不知道如何 spring 检查有效的 session 在 DB session 池的情况下,但有时它必须访问 DB read all session's 这样它就可以找出哪些 session ID 是有效的(我猜这是为每个之后完成的 - 至少是登录请求)。当有效的 session 由该池同时定义时,如何在您的情况下将无效 session 保留在数据库 session 池中?