6

Currently I was experiencing the new Spring reactive stack, and want to use reactive features in Spring Session 2.0.

In traditional Servlet approach, Spring Session provides a HttpSessionStrategy to detect session in cookie or request headers. It is easy to use HeaderHttpSessionStrategy to implement a token like authentication(by default the he name is X-AUTH-TOKEN) for RESTful APIs.

Spring 5 core provides a WebSessionIdResolver to do the same thing for Reactive environment.

But when use it with Spring Security and wish it worked as traditional way, I can not get it work.

The SessionConfig file.

@EnableSpringWebSession
public class SessionConfig {

    @Bean
    public ReactorSessionRepository sessionRepository() {
        return new MapReactorSessionRepository(new ConcurrentHashMap<>());
    }

    @Bean
    public WebSessionIdResolver headerWebSessionIdResolver() {
        HeaderWebSessionIdResolver resolver = new HeaderWebSessionIdResolver();
        resolver.setHeaderName("X-SESSION-ID");
        return resolver;
    }
}

The partial SecurityConfig.

@EnableWebFluxSecurity
class SecurityConfig {

    @Bean
    SecurityWebFilterChain springWebFilterChain(HttpSecurity http) throws Exception {
        return http
            .authorizeExchange()
            .pathMatchers(HttpMethod.GET, "/posts/**").permitAll()
            .pathMatchers(HttpMethod.DELETE, "/posts/**").hasRole("ADMIN")
            //.pathMatchers("/users/{user}/**").access(this::currentUserMatchesPath)
            .anyExchange().authenticated()
            .and()
            .build();
}

A test rest controller file, it returns the current Session ID.

@RestController
public class SessionRestController {


    @GetMapping("/sessionId")
    public Map<String, String> sessionId(WebSession session){
        Map<String, String> map = new HashMap<>();
        map.put("id", session.getId());
       return map ;
    }

}

When I started up the application, and use curl to access the /sessionId, there is no session info the response header.

curl -v -u "user:password" http://localhost:8080/sessionId

And I got the session id in the query result and put it into request headers to access the protected resources and got 401.

curl -v -X POST -H "X-SESSION-ID:xxxx" http://localhost:8080/posts

Update: A working sample can be found here.

Hantsy
  • 8,006
  • 7
  • 64
  • 109

1 Answers1

2

Spring Framework's spring-web module defaults to using it's CookieWebSessionIdResolver, which is based on cookies. If you create an alternative bean of type HeaderWebSessionIdResolver, it will get picked up automatically by Spring Session and switch to a header-based strategy.

In either strategy, it's geared to read the incoming ServerExchange headers, and look up the session id, whether that is reading the Cookie header or the SESSION http header.

These strategies also create response headers, whether that is a set-cookie directive for the client (web browser or your code) to populate the Cookie, or to give you the SESSION header (default name for the HeaderWebSessionIdResolver's header name).

gregturn
  • 2,625
  • 3
  • 25
  • 40
  • I know this clearly, and I have read the test codes about `WebSessionIdResolver`. But it does not work as expected when used it with Spring Session and Spring Security in my sample. I have used `curl` to test my APIs, the Session info was not appended into the response header, and also not verify the session I'v got from the first request in the further steps. – Hantsy Oct 20 '17 at 05:35
  • 2
    Updated my codes to Spring Boot 2.0.0.M6 and make it work, check the [sample codes](https://github.com/hantsy/spring-reactive-sample/tree/master/session-header). – Hantsy Nov 25 '17 at 08:40