Search code examples
javaspring-boothttpsessionspring-sessionlettuce

RedisHttpSession is creating different sessionIds for requests from the same browser


So I'm basically using RedisHttpSession for session management. I've created this login API which stores the Staff object in the session when the login is successful. request.getSession().setAttribute("staff", staff); And in other APIs, I verify if a valid staff is logged in and if not I redirect them to the login page. Staff staff = (Staff) request.getSession().getAttribute("staff"); Now when I tested this whole scenario with Postman, it worked as expected but, I staged it on the server, and request.getSession().getId() is different in each request.

The other thing that I noticed was that when I was sending requests from Postman, I saw cookies being stored but there were no cookies on the browser.

Why is the sessionId different in each request? How do I solve this issue?


Solution

  • HttpSession was creating a new SessionId every time because the cookie wasn't being stored in the browser. And to handle that, I created a new @Configuration:

    @Configuration
    public class CorsConfig {
    
        @Bean
        public WebMvcConfigurer corsConfigurer() {
            return new WebMvcConfigurer() {
                public void addCorsMappings(CorsRegistry registry) {
                    registry.addMapping("/**").allowedMethods("GET", "POST", "PUT", "DELETE")
                            .allowedOrigins("http://localhost:4200", "https://sub.domain.com",
                                    "https://sub2.domain.com")
                            .allowedHeaders("*").allowCredentials(true);
                }
            };
        }
    }
    

    This will make the browser save cookies but this by itself is not enough for everything to work well. You'll have to modify your requests on the frontend as well. Add withCredentials: true to your request like:

        const httpOptions = {
          params: new HttpParams({ encoder: new CustomHttpUrlEncodingCodec() })
            .set('fileType', fileType.toString())
            .set('jobDetailsID', jobDetailsID),
          headers: new HttpHeaders().set('ngsw-bypass', 'true'),
          withCredentials: true
        }
    

    Or you can create a HttpInterceptor and handle all requests:

    @Injectable()
    export class CustomInterceptor implements HttpInterceptor { 
    
        intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    
            request = request.clone({
                withCredentials: true
            });
    
            return next.handle(request);
        }
    }
    
    @NgModule({
      bootstrap: [AppComponent],
      imports: [...],
      providers: [
        {
          provide: HTTP_INTERCEPTORS,
          useClass: CustomInterceptor ,
          multi: true
        }
      ]
    })
    export class AppModule {}