Description
Describe the bug
version:2.4.3
when a user after logging in , RedisIndexedSessionRepository will add sessionid to redis key:
"sessionAttr:org.springframework.session.FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME" type of set,
the question is if you set save-mode to always, the sessionId will never be remove from this set after you call request.invalidate()
spring.session.redis.save-mode=always
To Reproduce
- config
spring.session.redis.save-mode=always
- login any user:test, just create sessionId
- logout user:test,call request.invalidate()
- look data in redis ,the sessionId still in "sessionAttr:org.springframework.session.FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME:test"
Expected behavior
when call request.invalidate()
redis remove sessionid from redis set :"sessionAttr:org.springframework.session.FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME:test"
** other **
after set spring.session.redis.save-mode=always
in Reproduce3 put all attributes to this.delta every RedisSession instance
if (this.isNew || (RedisIndexedSessionRepository.this.saveMode == SaveMode.ALWAYS)) {
getAttributeNames().forEach((attributeName) -> this.delta.put(getSessionAttrNameKey(attributeName),
cached.getAttribute(attributeName)));
}
then clean sessionId from redis set
private void cleanupPrincipalIndex(RedisSession session) {
String sessionId = session.getId();
Map<String, String> indexes = RedisIndexedSessionRepository.this.indexResolver.resolveIndexesFor(session);
String principal = indexes.get(PRINCIPAL_NAME_INDEX_NAME);
if (principal != null) {
this.sessionRedisOperations.boundSetOps(getPrincipalKey(principal)).remove(sessionId);
}
}
but at last call saveDelta() re add sessionId
private void saveDelta() {
if (this.delta.isEmpty()) {
return;
}
String sessionId = getId();
getSessionBoundHashOperations(sessionId).putAll(this.delta);
String principalSessionKey = getSessionAttrNameKey(
FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME);
String securityPrincipalSessionKey = getSessionAttrNameKey(SPRING_SECURITY_CONTEXT);
if (this.delta.containsKey(principalSessionKey) || this.delta.containsKey(securityPrincipalSessionKey)) {
if (this.originalPrincipalName != null) {
String originalPrincipalRedisKey = getPrincipalKey(this.originalPrincipalName);
RedisIndexedSessionRepository.this.sessionRedisOperations.boundSetOps(originalPrincipalRedisKey)
.remove(sessionId);
}
Map<String, String> indexes = RedisIndexedSessionRepository.this.indexResolver.resolveIndexesFor(this);
String principal = indexes.get(PRINCIPAL_NAME_INDEX_NAME);
this.originalPrincipalName = principal;
if (principal != null) {
String principalRedisKey = getPrincipalKey(principal);
RedisIndexedSessionRepository.this.sessionRedisOperations.boundSetOps(principalRedisKey)
.add(sessionId);
}
}
this.delta = new HashMap<>(this.delta.size());
Long originalExpiration = (this.originalLastAccessTime != null)
? this.originalLastAccessTime.plus(getMaxInactiveInterval()).toEpochMilli() : null;
RedisIndexedSessionRepository.this.expirationPolicy.onExpirationUpdated(originalExpiration, this);
}
Please help to check whether there is this problem