Fixed - PRINCIPAL_NAME_INDEX_NAME key is not created in redis. SessionExpiredEvent is not triggered. #2153

pull/2168/head
Nikita Koksharov 6 years ago
parent d1a8936aec
commit 8d78bf5197

@ -24,6 +24,7 @@ import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.redisson.api.RBucket;
import org.redisson.api.RMap;
import org.redisson.api.RPatternTopic;
import org.redisson.api.RSet;
@ -54,6 +55,8 @@ import org.springframework.util.StringUtils;
public class RedissonSessionRepository implements FindByIndexNameSessionRepository<RedissonSessionRepository.RedissonSession>,
PatternMessageListener<String> {
static final String SESSION_ATTR_PREFIX = "session-attr:";
final class RedissonSession implements Session {
private String principalName;
@ -63,7 +66,6 @@ public class RedissonSessionRepository implements FindByIndexNameSessionReposito
RedissonSession() {
this.delegate = new MapSession();
map = redisson.getMap(keyPrefix + delegate.getId(), new CompositeCodec(StringCodec.INSTANCE, redisson.getConfig().getCodec()));
principalName = resolvePrincipal(delegate);
Map<String, Object> newMap = new HashMap<String, Object>(3);
newMap.put("session:creationTime", delegate.getCreationTime().toEpochMilli());
@ -79,35 +81,15 @@ public class RedissonSessionRepository implements FindByIndexNameSessionReposito
}
private void updateExpiration() {
if (delegate.getMaxInactiveInterval().getSeconds() >= 0) {
map.expire(delegate.getMaxInactiveInterval().getSeconds(), TimeUnit.SECONDS);
if (delegate.getMaxInactiveInterval().getSeconds() > 0) {
redisson.getBucket(getExpiredKey(delegate.getId())).set("", delegate.getMaxInactiveInterval().getSeconds(), TimeUnit.SECONDS);
}
}
RedissonSession(String sessionId) {
this.delegate = new MapSession(sessionId);
map = redisson.getMap(keyPrefix + sessionId, new CompositeCodec(StringCodec.INSTANCE, redisson.getConfig().getCodec()));
principalName = resolvePrincipal(delegate);
}
public void delete() {
map.delete();
}
public boolean load() {
Set<Entry<String, Object>> entrySet = map.readAllEntrySet();
for (Entry<String, Object> entry : entrySet) {
if ("session:creationTime".equals(entry.getKey())) {
delegate.setCreationTime(Instant.ofEpochMilli((Long) entry.getValue()));
} else if ("session:lastAccessedTime".equals(entry.getKey())) {
delegate.setLastAccessedTime(Instant.ofEpochMilli((Long) entry.getValue()));
} else if ("session:maxInactiveInterval".equals(entry.getKey())) {
delegate.setMaxInactiveInterval(Duration.ofSeconds((Long) entry.getValue()));
} else {
delegate.setAttribute(entry.getKey(), entry.getValue());
}
}
return !entrySet.isEmpty();
RedissonSession(MapSession session) {
this.delegate = session;
map = redisson.getMap(keyPrefix + session.getId(), new CompositeCodec(StringCodec.INSTANCE, redisson.getConfig().getCodec()));
principalName = resolvePrincipal(this);
}
@Override
@ -135,12 +117,10 @@ public class RedissonSessionRepository implements FindByIndexNameSessionReposito
delegate.setAttribute(attributeName, attributeValue);
if (map != null) {
map.fastPut(attributeName, attributeValue);
String securityPrincipalSessionAttr = getSessionAttrNameKey(SPRING_SECURITY_CONTEXT);
map.fastPut(getSessionAttrNameKey(attributeName), attributeValue);
if (attributeName.equals(PRINCIPAL_NAME_INDEX_NAME)
|| attributeName.equals(securityPrincipalSessionAttr)) {
|| attributeName.equals(SPRING_SECURITY_CONTEXT)) {
// remove old
if (principalName != null) {
RSet<String> set = getPrincipalSet(principalName);
@ -169,7 +149,7 @@ public class RedissonSessionRepository implements FindByIndexNameSessionReposito
delegate.removeAttribute(attributeName);
if (map != null) {
map.fastRemove(attributeName);
map.fastRemove(getSessionAttrNameKey(attributeName));
}
}
@ -215,14 +195,22 @@ public class RedissonSessionRepository implements FindByIndexNameSessionReposito
@Override
public String changeSessionId() {
String oldId = delegate.getId();
String id = delegate.changeSessionId();
if (redisson.getConfig().isClusterConfig()) {
Map<String, Object> oldState = map.readAllMap();
map.delete();
map = redisson.getMap(keyPrefix + id, map.getCodec());
map.putAll(oldState);
RBucket<String> bucket = redisson.getBucket(getExpiredKey(oldId));
long remainTTL = bucket.remainTimeToLive();
bucket.delete();
redisson.getBucket(getExpiredKey(id)).set("", remainTTL, TimeUnit.MILLISECONDS);
} else {
map.rename(keyPrefix + id);
redisson.getBucket(getExpiredKey(oldId)).rename(getExpiredKey(id));
}
return id;
}
@ -263,6 +251,28 @@ public class RedissonSessionRepository implements FindByIndexNameSessionReposito
this(redissonClient, eventPublisher, null);
}
private MapSession loadSession(String sessionId) {
RMap<String, Object> map = redisson.getMap(keyPrefix + sessionId, new CompositeCodec(StringCodec.INSTANCE, redisson.getConfig().getCodec()));
Set<Entry<String, Object>> entrySet = map.readAllEntrySet();
if (entrySet.isEmpty()) {
return null;
}
MapSession delegate = new MapSession(sessionId);
for (Entry<String, Object> entry : entrySet) {
if ("session:creationTime".equals(entry.getKey())) {
delegate.setCreationTime(Instant.ofEpochMilli((Long) entry.getValue()));
} else if ("session:lastAccessedTime".equals(entry.getKey())) {
delegate.setLastAccessedTime(Instant.ofEpochMilli((Long) entry.getValue()));
} else if ("session:maxInactiveInterval".equals(entry.getKey())) {
delegate.setMaxInactiveInterval(Duration.ofSeconds((Long) entry.getValue()));
} else if (entry.getKey().startsWith(SESSION_ATTR_PREFIX)) {
delegate.setAttribute(entry.getKey().substring(SESSION_ATTR_PREFIX.length()), entry.getValue());
}
}
return delegate;
}
@Override
public void onMessage(CharSequence pattern, CharSequence channel, String body) {
if (createdTopic.getPatternNames().contains(pattern.toString())) {
@ -271,27 +281,29 @@ public class RedissonSessionRepository implements FindByIndexNameSessionReposito
publishEvent(new SessionCreatedEvent(this, session));
}
} else if (deletedTopic.getPatternNames().contains(pattern.toString())) {
if (!body.startsWith(keyPrefix)) {
if (!body.startsWith(getExpiredKeyPrefix())) {
return;
}
String id = body.split(keyPrefix)[1];
RedissonSession session = new RedissonSession(id);
if (session.load()) {
String id = body.split(getExpiredKeyPrefix())[1];
MapSession mapSession = loadSession(id);
if (mapSession != null) {
RedissonSession session = new RedissonSession(mapSession);
session.clearPrincipal();
publishEvent(new SessionDeletedEvent(this, session));
}
publishEvent(new SessionDeletedEvent(this, session));
} else if (expiredTopic.getPatternNames().contains(pattern.toString())) {
if (!body.startsWith(keyPrefix)) {
if (!body.startsWith(getExpiredKeyPrefix())) {
return;
}
String id = body.split(keyPrefix)[1];
RedissonSession session = new RedissonSession(id);
if (session.load()) {
String id = body.split(getExpiredKeyPrefix())[1];
MapSession mapSession = loadSession(id);
if (mapSession != null) {
RedissonSession session = new RedissonSession(mapSession);
session.clearPrincipal();
publishEvent(new SessionExpiredEvent(this, session));
}
publishEvent(new SessionExpiredEvent(this, session));
}
}
@ -323,11 +335,11 @@ public class RedissonSessionRepository implements FindByIndexNameSessionReposito
@Override
public RedissonSession findById(String id) {
RedissonSession session = new RedissonSession(id);
if (!session.load() || session.isExpired()) {
MapSession mapSession = loadSession(id);
if (mapSession == null || mapSession.isExpired()) {
return null;
}
return session;
return new RedissonSession(mapSession);
}
@Override
@ -337,8 +349,10 @@ public class RedissonSessionRepository implements FindByIndexNameSessionReposito
return;
}
redisson.getBucket(getExpiredKey(id)).delete();
session.clearPrincipal();
session.delete();
session.setMaxInactiveInterval(Duration.ZERO);
}
public void setKeyPrefix(String keyPrefix) {
@ -364,6 +378,14 @@ public class RedissonSessionRepository implements FindByIndexNameSessionReposito
return getEventsChannelPrefix() + sessionId;
}
String getExpiredKey(String sessionId) {
return getExpiredKeyPrefix() + sessionId;
}
String getExpiredKeyPrefix() {
return keyPrefix + "sessions:expires:";
}
String getEventsChannelPrefix() {
return keyPrefix + "created:event:";
}
@ -373,7 +395,7 @@ public class RedissonSessionRepository implements FindByIndexNameSessionReposito
}
String getSessionAttrNameKey(String name) {
return "session-attr:" + name;
return SESSION_ATTR_PREFIX + name;
}
@Override

@ -17,7 +17,6 @@ package org.redisson.spring.session.config;
import java.util.Map;
import net.bytebuddy.build.ToStringPlugin;
import org.redisson.api.RedissonClient;
import org.redisson.spring.session.RedissonSessionRepository;
import org.springframework.context.ApplicationEventPublisher;
@ -27,7 +26,6 @@ import org.springframework.context.annotation.ImportAware;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.session.config.annotation.web.http.SpringHttpSessionConfiguration;
import org.springframework.util.StringUtils;
/**
* Exposes the SessionRepositoryFilter as the bean

Loading…
Cancel
Save