Skip to content

Commit 466b8a1

Browse files
jeffrey-easyesirwinch
authored andcommitted
Fix race condition in SessionRegistryImpl
Adding/removing sessions from principals wasn't atomic. If one thread removed the last session from a principal while another thread added a new one, the addition could be lost. Fixes gh-3189
1 parent 0532b6e commit 466b8a1

File tree

1 file changed

+30
-28
lines changed

1 file changed

+30
-28
lines changed

core/src/main/java/org/springframework/security/core/session/SessionRegistryImpl.java

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -132,13 +132,18 @@ public void registerNewSession(String sessionId, Object principal) {
132132
sessionIds.put(sessionId,
133133
new SessionInformation(principal, sessionId, new Date()));
134134

135-
Set<String> sessionsUsedByPrincipal = principals.computeIfAbsent(principal, key -> new CopyOnWriteArraySet<>());
136-
sessionsUsedByPrincipal.add(sessionId);
135+
principals.compute(principal, (key, sessionsUsedByPrincipal) -> {
136+
if (sessionsUsedByPrincipal == null) {
137+
sessionsUsedByPrincipal = new CopyOnWriteArraySet<>();
138+
}
139+
sessionsUsedByPrincipal.add(sessionId);
137140

138-
if (logger.isTraceEnabled()) {
139-
logger.trace("Sessions used by '" + principal + "' : "
140-
+ sessionsUsedByPrincipal);
141-
}
141+
if (logger.isTraceEnabled()) {
142+
logger.trace("Sessions used by '" + principal + "' : "
143+
+ sessionsUsedByPrincipal);
144+
}
145+
return sessionsUsedByPrincipal;
146+
});
142147
}
143148

144149
public void removeSessionInformation(String sessionId) {
@@ -157,32 +162,29 @@ public void removeSessionInformation(String sessionId) {
157162

158163
sessionIds.remove(sessionId);
159164

160-
Set<String> sessionsUsedByPrincipal = principals.get(info.getPrincipal());
161-
162-
if (sessionsUsedByPrincipal == null) {
163-
return;
164-
}
165-
166-
if (logger.isDebugEnabled()) {
167-
logger.debug("Removing session " + sessionId
168-
+ " from principal's set of registered sessions");
169-
}
165+
principals.computeIfPresent(info.getPrincipal(), (key, sessionsUsedByPrincipal) -> {
166+
if (logger.isDebugEnabled()) {
167+
logger.debug("Removing session " + sessionId
168+
+ " from principal's set of registered sessions");
169+
}
170170

171-
sessionsUsedByPrincipal.remove(sessionId);
171+
sessionsUsedByPrincipal.remove(sessionId);
172172

173-
if (sessionsUsedByPrincipal.isEmpty()) {
174-
// No need to keep object in principals Map anymore
175-
if (logger.isDebugEnabled()) {
176-
logger.debug("Removing principal " + info.getPrincipal()
177-
+ " from registry");
173+
if (sessionsUsedByPrincipal.isEmpty()) {
174+
// No need to keep object in principals Map anymore
175+
if (logger.isDebugEnabled()) {
176+
logger.debug("Removing principal " + info.getPrincipal()
177+
+ " from registry");
178+
}
179+
sessionsUsedByPrincipal = null;
178180
}
179-
principals.remove(info.getPrincipal());
180-
}
181181

182-
if (logger.isTraceEnabled()) {
183-
logger.trace("Sessions used by '" + info.getPrincipal() + "' : "
184-
+ sessionsUsedByPrincipal);
185-
}
182+
if (logger.isTraceEnabled()) {
183+
logger.trace("Sessions used by '" + info.getPrincipal() + "' : "
184+
+ sessionsUsedByPrincipal);
185+
}
186+
return sessionsUsedByPrincipal;
187+
});
186188
}
187189

188190
}

0 commit comments

Comments
 (0)