Track change of MongoSession's id to properly delete.

When a session is made invalid and changed to a new one, the old one must be deleted from MongoDB at the next save().

Resolves #116.
This commit is contained in:
Greg Turnquist
2019-10-09 09:05:09 -05:00
parent d6206cc3e7
commit 245d69ab29
5 changed files with 286 additions and 10 deletions

View File

@@ -43,6 +43,7 @@ public class MongoSession implements Session {
private static final char DOT_COVER_CHAR = '';
private String id;
private String originalSessionId;
private long createdMillis = System.currentTimeMillis();
private long accessedMillis;
private long intervalSeconds;
@@ -60,6 +61,7 @@ public class MongoSession implements Session {
public MongoSession(String id, long maxInactiveIntervalInSeconds) {
this.id = id;
this.originalSessionId = id;
this.intervalSeconds = maxInactiveIntervalInSeconds;
setLastAccessedTime(Instant.ofEpochMilli(this.createdMillis));
}
@@ -72,6 +74,7 @@ public class MongoSession implements Session {
return attributeName.replace(DOT_COVER_CHAR, '.');
}
@Override
public String changeSessionId() {
String changedId = UUID.randomUUID().toString();
@@ -85,10 +88,12 @@ public class MongoSession implements Session {
return (T) this.attrs.get(coverDot(attributeName));
}
@Override
public Set<String> getAttributeNames() {
return this.attrs.keySet().stream().map(MongoSession::uncoverDot).collect(Collectors.toSet());
}
@Override
public void setAttribute(String attributeName, Object attributeValue) {
if (attributeValue == null) {
@@ -98,10 +103,12 @@ public class MongoSession implements Session {
}
}
@Override
public void removeAttribute(String attributeName) {
this.attrs.remove(coverDot(attributeName));
}
@Override
public Instant getCreationTime() {
return Instant.ofEpochMilli(this.createdMillis);
}
@@ -110,24 +117,29 @@ public class MongoSession implements Session {
this.createdMillis = created;
}
@Override
public Instant getLastAccessedTime() {
return Instant.ofEpochMilli(this.accessedMillis);
}
@Override
public void setLastAccessedTime(Instant lastAccessedTime) {
this.accessedMillis = lastAccessedTime.toEpochMilli();
this.expireAt = Date.from(lastAccessedTime.plus(Duration.ofSeconds(this.intervalSeconds)));
}
@Override
public Duration getMaxInactiveInterval() {
return Duration.ofSeconds(this.intervalSeconds);
}
@Override
public void setMaxInactiveInterval(Duration interval) {
this.intervalSeconds = interval.getSeconds();
}
@Override
public boolean isExpired() {
return this.intervalSeconds >= 0 && new Date().after(this.expireAt);
}
@@ -140,14 +152,15 @@ public class MongoSession implements Session {
if (o == null || getClass() != o.getClass())
return false;
MongoSession that = (MongoSession) o;
return Objects.equals(id, that.id);
return Objects.equals(this.id, that.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
return Objects.hash(this.id);
}
@Override
public String getId() {
return this.id;
}
@@ -159,4 +172,12 @@ public class MongoSession implements Session {
public void setExpireAt(final Date expireAt) {
this.expireAt = expireAt;
}
boolean hasChangedSessionId() {
return !getId().equals(this.originalSessionId);
}
String getOriginalSessionId() {
return this.originalSessionId;
}
}

View File

@@ -15,6 +15,8 @@
*/
package org.springframework.session.data.mongo;
import static org.springframework.data.mongodb.core.query.Criteria.*;
import static org.springframework.data.mongodb.core.query.Query.*;
import static org.springframework.session.data.mongo.MongoSessionUtils.*;
import java.time.Duration;
@@ -34,8 +36,6 @@ import org.springframework.session.ReactiveSessionRepository;
import org.springframework.session.events.SessionCreatedEvent;
import org.springframework.session.events.SessionDeletedEvent;
import com.mongodb.DBObject;
/**
* A {@link ReactiveSessionRepository} implementation that uses Spring Data MongoDB.
*
@@ -92,12 +92,20 @@ public class ReactiveMongoSessionRepository
@Override
public Mono<Void> save(MongoSession session) {
DBObject dbObject = convertToDBObject(this.mongoSessionConverter, session);
if (dbObject != null) {
return this.mongoOperations.save(dbObject, this.collectionName).then();
} else {
return Mono.empty();
}
return Mono //
.justOrEmpty(convertToDBObject(this.mongoSessionConverter, session)) //
.flatMap(dbObject -> {
if (session.hasChangedSessionId()) {
return this.mongoOperations
.remove(query(where("_id").is(session.getOriginalSessionId())), this.collectionName) //
.then(this.mongoOperations.save(dbObject, this.collectionName));
} else {
return this.mongoOperations.save(dbObject, this.collectionName);
}
}) //
.then();
}
@Override