Manually expire web sessions
Instead of relying on the cache implementation to kill web sessions past the time the admin has configured as allowed, track the end time when the session was created and initially stored in the cache. If a valid session key is found in the cache, but it expired before now, invalidate the key and report it as not found. Sessions are usually updated in the cache every 50% of the maxAge, rotating the key and changing the cookie during this time. During one of these half-expired rotations the session will have a new expire time set, keeping it alive for a longer time window since the user is still active. This saves the cache from needing to update the on access timer on every request, especially for disk based caches that try to save the web_sessions across server restarts. While we are poking at this cache, use String as the cache key rather than Key now that the H2 based system doesn't need to use the key for version checks. This simplifies the BloomFilter logic inside of the disk based cache to be able to hash the token more quickly. Change-Id: I318e38b2382b7f5ea1188df3ddc7ec6703a5fd3c
This commit is contained in:
@@ -170,7 +170,7 @@ public final class CacheBasedWebSession implements WebSession {
|
||||
/** Set the user account for this current request only. */
|
||||
public void setUserAccountId(Account.Id id) {
|
||||
key = new Key("id:" + id);
|
||||
val = new Val(id, 0, false, null, "");
|
||||
val = new Val(id, 0, false, null, "", 0);
|
||||
}
|
||||
|
||||
public void logout() {
|
||||
|
@@ -43,6 +43,7 @@ import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Singleton
|
||||
class WebSessionManager {
|
||||
@@ -104,7 +105,9 @@ class WebSessionManager {
|
||||
final long halfAgeRefresh = sessionMaxAgeMillis >>> 1;
|
||||
final long minRefresh = MILLISECONDS.convert(1, HOURS);
|
||||
final long refresh = Math.min(halfAgeRefresh, minRefresh);
|
||||
final long refreshCookieAt = now() + refresh;
|
||||
final long now = now();
|
||||
final long refreshCookieAt = now + refresh;
|
||||
final long expiresAt = now + sessionMaxAgeMillis;
|
||||
|
||||
if (xsrfToken == null) {
|
||||
// If we don't yet have a token for this session, establish one.
|
||||
@@ -115,7 +118,8 @@ class WebSessionManager {
|
||||
xsrfToken = CookieBase64.encode(rnd);
|
||||
}
|
||||
|
||||
Val val = new Val(who, refreshCookieAt, remember, lastLogin, xsrfToken);
|
||||
Val val = new Val(who, refreshCookieAt, remember,
|
||||
lastLogin, xsrfToken, expiresAt);
|
||||
self.put(key, val);
|
||||
return val;
|
||||
}
|
||||
@@ -137,7 +141,12 @@ class WebSessionManager {
|
||||
}
|
||||
|
||||
Val get(final Key key) {
|
||||
return self.get(key);
|
||||
Val val = self.get(key);
|
||||
if (val != null && val.expiresAt <= now()) {
|
||||
self.remove(key);
|
||||
return null;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
void destroy(final Key key) {
|
||||
@@ -184,15 +193,18 @@ class WebSessionManager {
|
||||
private transient boolean persistentCookie;
|
||||
private transient AccountExternalId.Key externalId;
|
||||
private transient String xsrfToken;
|
||||
private transient long expiresAt;
|
||||
|
||||
Val(final Account.Id accountId, final long refreshCookieAt,
|
||||
final boolean persistentCookie, final AccountExternalId.Key externalId,
|
||||
final String xsrfToken) {
|
||||
final String xsrfToken,
|
||||
final long expiresAt) {
|
||||
this.accountId = accountId;
|
||||
this.refreshCookieAt = refreshCookieAt;
|
||||
this.persistentCookie = persistentCookie;
|
||||
this.externalId = externalId;
|
||||
this.xsrfToken = xsrfToken;
|
||||
this.expiresAt = expiresAt;
|
||||
}
|
||||
|
||||
Account.Id getAccountId() {
|
||||
@@ -233,6 +245,9 @@ class WebSessionManager {
|
||||
writeVarInt32(out, 5);
|
||||
writeString(out, xsrfToken);
|
||||
|
||||
writeVarInt32(out, 6);
|
||||
writeFixInt64(out, expiresAt);
|
||||
|
||||
writeVarInt32(out, 0);
|
||||
}
|
||||
|
||||
@@ -257,10 +272,16 @@ class WebSessionManager {
|
||||
case 5:
|
||||
xsrfToken = readString(in);
|
||||
continue;
|
||||
case 6:
|
||||
expiresAt = readFixInt64(in);
|
||||
continue;
|
||||
default:
|
||||
throw new IOException("Unknown tag found in object: " + tag);
|
||||
}
|
||||
}
|
||||
if (expiresAt == 0) {
|
||||
expiresAt = refreshCookieAt + TimeUnit.HOURS.toMillis(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user