How to save the request body after reading it in the ServerAuthenticationConverter?

Tags: , , , ,



Guys! maybe someone faced the problem of getting the request body..

I am trying to friend Spring WebFlux + Security: I use SecurityConfig

@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
public class SecurityConfig {
...

where I set

.addFilterAt(authenticationWebFilter(), SecurityWebFiltersOrder.AUTHENTICATION)

for check authentication

    private AuthenticationWebFilter authenticationWebFilter() {
        AuthenticationWebFilter authenticationWebFilter = new AuthenticationWebFilter(new AuthManager());
        authenticationWebFilter.setServerAuthenticationConverter(new AuthDataConverter());
        return authenticationWebFilter;
    }

I have a custom Converter (AuthDataConverter) and a custom Manager (AuthManager). When I do POST http Request I am falling in Converter: inside of the Converter – I get Headers and Body of Request:

import org.springframework.security.core.Authentication;
import org.springframework.security.web.server.authentication.ServerAuthenticationConverter;
import org.springframework.web.server.ServerWebExchange;

public class AuthDataConverter implements ServerAuthenticationConverter {
...
    @Override
    public Mono<Authentication> convert(ServerWebExchange exchange) {
        
        HttpHeaders headers = exchange.getRequest().getHeaders();
        Flux<DataBuffer> body = exchange.getRequest().getBody();
        ...
        Mono<String> m = decodeToString(body);

        return m.map(jsonBody -> {
            Authentication auth = new MyAuthData(headers, jsonBody);
            return auth;
        });
}

and all good – AuthDataConverter gets request params and send in AuthManager:

import org.springframework.security.authentication.ReactiveAuthenticationManager;
import org.springframework.security.core.Authentication;

public class AuthManager implements ReactiveAuthenticationManager {
...
    @Override
    public Mono<Authentication> authenticate(Authentication auth) {
    //check auth object 
    }

}

But! Problem: in next step, where I am falling in Controller:

@RestController
@RequestMapping("/test")
public class TestController {

    @PostMapping("/addParam")
    public Response<MyParam> addParam(@RequestBody Mono<MyParam> param) {
      //I can't go inside because the request body has already been read in AuthDataConverter
      //How can save body of request?
    }

Answer

After Reactor HTTP Request Body is subscribed once, the result of next subscribe is empty. This is because Reactor sets the source of HTTP Request Body as FluxRecive, which is a dynamic publisher that publishes the message body as HTTP Request. Therefore, when the HTTP Request message body is subscribed once, all subsequent subscribes are empty. Because the body of the HTTP Request is only sent once.

For me helped this article: https://www.programmersought.com/article/47663615530/



Source: stackoverflow