Add ExpiringSession setLastAccessedTime

Previously SessionRepository had to update the lastAccessTime when it was
loaded. This prevented inspecting the last access time. For example,
listing all the sessions for a specific user. Furthermore, it is
unintuitive that a read operation would update attributes on the domain
model.

This change introduces ExpiringSession setLastAccessedTime to allow setting
the expiration on the interface. This means that the SessionRepositoryFilter
can update the last accessed time.

Fixes gh-272
This commit is contained in:
Rob Winch
2015-11-17 10:47:42 -06:00
parent 8bd29c1ab2
commit ee09a9e863
8 changed files with 25 additions and 15 deletions

View File

@@ -30,6 +30,13 @@ public interface ExpiringSession extends Session {
*/
long getCreationTime();
/**
* Sets the last accessed time in milliseconds since midnight of 1/1/1970 GMT
*
* @param lastAccessedTime the last accessed time in milliseconds since midnight of 1/1/1970 GMT
*/
void setLastAccessedTime(long lastAccessedTime);
/**
* Gets the last time this {@link Session} was accessed expressed in milliseconds since midnight of 1/1/1970 GMT
*

View File

@@ -81,9 +81,7 @@ public class MapSessionRepository implements SessionRepository<ExpiringSession>
delete(saved.getId());
return null;
}
MapSession result = new MapSession(saved);
result.setLastAccessedTime(System.currentTimeMillis());
return result;
return new MapSession(saved);
}
public void delete(String id) {

View File

@@ -49,12 +49,6 @@ public interface SessionRepository<S extends Session> {
/**
* Gets the {@link Session} by the {@link Session#getId()} or null if no {@link Session} is found.
*
* <p>
* If the {@link Session} extends {@link ExpiringSession}, then {@link ExpiringSession#getLastAccessedTime()} will be
* updated on the returned object. In order to persist this change, {@link #save(Session)} must be invoked on the returned
* instance.
* </p>
*
* @param id the {@link org.springframework.session.Session#getId()} to lookup
* @return the {@link Session} by the {@link Session#getId()} or null if no {@link Session} is found.
*/

View File

@@ -365,7 +365,6 @@ public class RedisOperationsSessionRepository implements FindByPrincipalNameSess
for(Object id : sessionIds) {
RedisSession session = getSession((String) id);
if(session != null) {
session.setLastAccessedTime(session.originalLastAccessTime);
sessions.put(session.getId(), session);
}
}
@@ -392,7 +391,6 @@ public class RedisOperationsSessionRepository implements FindByPrincipalNameSess
}
RedisSession result = new RedisSession(loaded);
result.originalLastAccessTime = loaded.getLastAccessedTime();
result.setLastAccessedTime(System.currentTimeMillis());
return result;
}

View File

@@ -242,7 +242,7 @@ public class SessionRepositoryFilter<S extends ExpiringSession> extends OncePerR
public boolean isRequestedSessionIdValid() {
if(requestedSessionIdValid == null) {
String sessionId = getRequestedSessionId();
S session = sessionId == null ? null : sessionRepository.getSession(sessionId);
S session = sessionId == null ? null : getSession(sessionId);
return isRequestedSessionIdValid(session);
}
@@ -260,6 +260,15 @@ public class SessionRepositoryFilter<S extends ExpiringSession> extends OncePerR
return getCurrentSession() == null && requestedSessionInvalidated;
}
private S getSession(String sessionId) {
S session = sessionRepository.getSession(sessionId);
if(session == null) {
return null;
}
session.setLastAccessedTime(System.currentTimeMillis());
return session;
}
@Override
public HttpSessionWrapper getSession(boolean create) {
HttpSessionWrapper currentSession = getCurrentSession();
@@ -268,7 +277,7 @@ public class SessionRepositoryFilter<S extends ExpiringSession> extends OncePerR
}
String requestedSessionId = getRequestedSessionId();
if(requestedSessionId != null) {
S session = sessionRepository.getSession(requestedSessionId);
S session = getSession(requestedSessionId);
if(session != null) {
this.requestedSessionIdValid = true;
currentSession = new HttpSessionWrapper(session, getServletContext());

View File

@@ -94,6 +94,10 @@ public class MapSessionTests {
return "id";
}
public void setLastAccessedTime(long lastAccessedTime) {
throw new UnsupportedOperationException();
}
public long getLastAccessedTime() {
return 0;
}

View File

@@ -319,7 +319,7 @@ public class RedisOperationsSessionRepositoryTests {
assertThat(session.getAttribute(attrName)).isEqualTo(expected.getAttribute(attrName));
assertThat(session.getCreationTime()).isEqualTo(expected.getCreationTime());
assertThat(session.getMaxInactiveIntervalInSeconds()).isEqualTo(expected.getMaxInactiveIntervalInSeconds());
assertThat(session.getLastAccessedTime()).isGreaterThanOrEqualTo(now);
assertThat(session.getLastAccessedTime()).isEqualTo(expected.getLastAccessedTime());
}

View File

@@ -126,7 +126,7 @@ public class SessionRepositoryFilterTests {
}
});
Thread.sleep(10L);
Thread.sleep(1L);
nextRequest();
doFilter(new DoInFilter() {