Skip to content

Commit 49a2841

Browse files
Add caching
1 parent 507c2bc commit 49a2841

1 file changed

Lines changed: 37 additions & 2 deletions

File tree

dhis-2/dhis-web-api/src/main/java/org/hisp/dhis/webapi/filter/SessionIdHeaderFilter.java

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343
import java.security.MessageDigest;
4444
import java.security.SecureRandom;
4545
import java.util.Base64;
46+
import java.util.concurrent.ConcurrentHashMap;
47+
import java.util.concurrent.TimeUnit;
4648
import javax.crypto.Cipher;
4749
import javax.crypto.spec.GCMParameterSpec;
4850
import javax.crypto.spec.SecretKeySpec;
@@ -71,6 +73,10 @@ public class SessionIdHeaderFilter extends OncePerRequestFilter {
7173
private static final String CIPHER_ALGO = "AES/GCM/NoPadding";
7274
private static final String HASH_ALGO = "SHA-256";
7375
private static final int KEY_LENGTH_BYTES = 32;
76+
private static final long CACHE_TTL_MILLIS = TimeUnit.MINUTES.toMillis(5);
77+
private static final int MAX_CACHE_SIZE = 10_000;
78+
private static final ConcurrentHashMap<String, CacheEntry> HEADER_CACHE =
79+
new ConcurrentHashMap<>();
7480

7581
private final boolean enabled;
7682
private final byte[] keyBytes;
@@ -107,8 +113,10 @@ protected void doFilterInternal(
107113
UserDetails userDetails = CurrentUserUtil.getCurrentUserDetails();
108114
HttpSession session = request.getSession(false);
109115
if (session != null) {
110-
String payload = userDetails.getUid() + ":" + hashSessionId(session.getId());
111-
response.addHeader(HEADER_NAME, encrypt(payload));
116+
String sessionHash = hashSessionId(session.getId());
117+
String cacheKey = userDetails.getUid() + ":" + sessionHash;
118+
String headerValue = getOrCreateHeaderValue(cacheKey);
119+
response.addHeader(HEADER_NAME, headerValue);
112120
}
113121
} catch (GeneralSecurityException ex) {
114122
log.error("Failed to encrypt session header payload", ex);
@@ -130,6 +138,31 @@ private String encrypt(String payload) throws GeneralSecurityException {
130138
return HEADER_VERSION_PREFIX + Base64.getUrlEncoder().withoutPadding().encodeToString(combined);
131139
}
132140

141+
private String getOrCreateHeaderValue(String cacheKey) throws GeneralSecurityException {
142+
long now = System.currentTimeMillis();
143+
CacheEntry cached = HEADER_CACHE.get(cacheKey);
144+
if (cached != null && cached.expiresAtMillis > now) {
145+
return cached.headerValue;
146+
}
147+
148+
if (cached != null) {
149+
HEADER_CACHE.remove(cacheKey, cached);
150+
}
151+
152+
String headerValue = encrypt(cacheKey);
153+
CacheEntry entry = new CacheEntry(headerValue, now + CACHE_TTL_MILLIS);
154+
HEADER_CACHE.put(cacheKey, entry);
155+
156+
if (HEADER_CACHE.size() > MAX_CACHE_SIZE) {
157+
HEADER_CACHE.entrySet().removeIf(e -> e.getValue().expiresAtMillis <= now);
158+
if (HEADER_CACHE.size() > MAX_CACHE_SIZE) {
159+
HEADER_CACHE.clear();
160+
}
161+
}
162+
163+
return headerValue;
164+
}
165+
133166
private static byte[] decodeKey(String token) {
134167
try {
135168
return Base64.getDecoder().decode(token);
@@ -143,4 +176,6 @@ private static String hashSessionId(String sessionId) throws GeneralSecurityExce
143176
byte[] hashed = digest.digest(sessionId.getBytes(StandardCharsets.UTF_8));
144177
return Base64.getUrlEncoder().withoutPadding().encodeToString(hashed);
145178
}
179+
180+
private record CacheEntry(String headerValue, long expiresAtMillis) {}
146181
}

0 commit comments

Comments
 (0)