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 池中?
我正在我的项目中实现 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 池中?