Closed theigl closed 1 week ago
I created a draft PR that shows what changes would be necessary to support my use case: https://github.com/spring-projects/spring-session/pull/3098
Hello @theigl. I'd like to know more about your use case and what you've tried.
Have you tried to do defaultCookieSerializer.setCookieMaxAge(Integer.MAX_VALUE);
? This way the cookie expiration time is long and you rely only on the session expiration time.
Manually extend the session cookie in response to user actions or a globally in a filter
This can probably be achieved with a custom filter, have you tried it? I'm unsure if you want to write the Set-Cookie
header back on every request the client makes.
Hi @marcusdacoregio!
Have you tried to do defaultCookieSerializer.setCookieMaxAge(Integer.MAX_VALUE);? This way the cookie expiration time is long and you rely only on the session expiration time.
This approach would work, but it feels a bit wrong. My session timeout is set to 30 minutes, so setting a persistent cookie with a very long lifetime will lead to a lot of requests for sessions that definitely do not exist anymore.
This can probably be achieved with a custom filter, have you tried it?
I did a quick prototype but soon realized that this is not trivial to implement. The filter has to be added after the session repository filter and it has to handle the case where the session is created or invalidated in the same request. There is no API for retrieving cookies from the HttpServletResponse
so I would need to set some attribute on the request to know that the session has been created or invalidated or wrap the response and expose the cookies that have been added.
I'm unsure if you want to write the Set-Cookie header back on every request the client makes.
I would probably not set in on every request but check the cookie expiration date and only extend it if at least a minute has passed since the last extension.
This approach would work, but it feels a bit wrong. My session timeout is set to 30 minutes, so setting a persistent cookie with a very long lifetime will lead to a lot of requests for sessions that definitely do not exist anymore.
I don't follow what you mean, if the session is expired the request will fail and a new session will be created for the client. It looks better than creating multiple sessions if the user closes the app.
I don't think it is trivial for the API to support that either, while it might make sense for your use case I don't feel yet that it is the right place to do it.
There is no API for retrieving cookies from the HttpServletResponse
You can retrieve the cookies from the HttpServletRequest
or you can retrieve the Set-Cookie
headers from the response.
Have you tried to do something like:
public class SessionExtenderFilter extends OncePerRequestFilter {
private final Clock clock = Clock.systemUTC();
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
filterChain.doFilter(request, response);
HttpSession session = request.getSession(false);
if (session == null) {
return;
}
for (Cookie cookie : request.getCookies()) {
if ("SESSION".equals(cookie.getName())) {
extendSessionCookieIfNeeded(session, response, cookie);
}
}
}
private void extendSessionCookieIfNeeded(HttpSession session, HttpServletResponse response, Cookie cookie) {
// you can also check any other attribute from the session here
int maxAge = cookie.getMaxAge();
Instant expires = this.clock.instant().plusSeconds(maxAge);
Instant now = this.clock.instant();
if (ChronoUnit.SECONDS.between(now, expires) < 60) {
cookie.setMaxAge(1800);
response.addCookie(cookie);
}
}
}
I would place this filter before the SessionRepositoryFilter
since it will run after the response is returned.
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
Thanks @marcusdacoregio. I think that will work for our use case. Thanks for taking the time to suggesting a workable solution!
Expected Behavior
We would like to store the session ID in a cookie with an expiration date that matches the session timeout. The cookie expiration date should be updated every time the user accesses the session.
Current Behavior
The session ID is stored in a session cookie by default. It is possible to override the cookie's
maxAge
inCookieSerializer
, but there is no way to refresh the cookie whenever the session is accessed and the cookie would simply expire aftermaxAge
, even if the session is still actively used.Context
We are using Capacitor to bundle our web application as a native app. Many users are closing the application instead of pausing it/moving it to the background, only to re-open it a minute later. Every time the app is closed, all session cookies are cleared and the user is associated with a new session. Using a persistent cookie that is extended on every session access, would be an elegant solution to this issue.
Possible workarounds: