Search code examples
springspring-mvcspring-session

Start a session from a given id in spring


How can I create a session in a spring mvc application from a given ID instead of a generated one?

I want to fixate the session. The fixation will be started by a trusted ui service. This trusted service forwards all requests. Thus the fixation can't begin in browser. It is not intended to do it without this ui service.

Providing a HttpSessionIdResolver bean does not work, since it only changes the location in HTTP response. Eg Session ID in HTTP header after authorization.

Are there any solutions without creating a shadow session management?

Session is required for keycloak integration. Guess it's not possible to use keycloak in stateless mode.

Thanks in advance


Solution

  • It is possible to fixate a session with spring-session.

    @Configuration
    @EnableSpringHttpSession
    public class SessionConfig {
    
      @Bean
      public HttpSessionIdResolver httpSessionIdResolver() {
        return new HttpSessionIdResolver() {
          public List<String> resolveSessionIds(HttpServletRequest request) {
            final var sessionId = request.getHeader("X-SessionId");
            request.setAttribute(SessionConfig.class.getName() + "SessionIdAttr", sessionId);
            return List.of(sessionId);
          }
    
          public void setSessionId(HttpServletRequest request, HttpServletResponse response, String sessionId) {}
          public void expireSession(HttpServletRequest request, HttpServletResponse response) {}
        };
      }
    
      @Bean
      public SessionRepository<MapSession> sessionRepository() {
        return new MapSessionRepository(new HashMap<>()) {
          @Override
          public MapSession createSession() {
            var sessionId =
                (String)RequestContextHolder
                    .currentRequestAttributes()
                    .getAttribute(SessionConfig.class.getName()+"SessionIdAttr", 0);
            final var session = super.createSession();
            if (sessionId != null) {
              session.setId(sessionId);
            }
            return session;
          }
        };
    }
    

    In #resolveSessionIds() you can read the ID and store for later use. createSession() is called when no session has been found and a new one is required. Here you can create the session with previously remembered ID in MapSession#setId(String).

    Even if is possible, IMO it is not a good idea. There might be other architectural solutions/problems.