Аутентификация (согласование) ExchangeFilterFunction - как использовать то же соединение, что и запрос? - PullRequest
0 голосов
/ 04 мая 2020

Я написал функцию ExchangeFilterFunction для поддержки аутентификации (Kerberos, NTLM, SPEN GO).

public class NegotiateExchangeFilterFunction implements ExchangeFilterFunction {

    private static final String AUTHORIZATION = "Authorization";
    @Autowired
    private TokenService tokenService;

    @Override
    public Mono<ClientResponse> filter(ClientRequest request, ExchangeFunction exchangeFunction) {
        ClientRequest clientRequestFrom = ClientRequest.from(request).headers(this::setAuthorizationHeader).build();

        return exchangeFunction.exchange(clientRequestFrom).flatMap(clientResponse -> {
            // Check HTTP Status Code 401
            if (clientResponse.statusCode().equals(HttpStatus.UNAUTHORIZED)) {
                this.tokenService.initializeClientContext(
                        this.tokenService.getContinueToken(clientResponse.headers().asHttpHeaders()));

                ClientRequest continueChallangeRequest = ClientRequest.from(clientRequestFrom)
                        .headers(this::setAuthorizationHeader)
                        .build();
                return exchangeFunction.exchange(continueChallangeRequest);
            }
            return Mono.just(clientResponse);
        });
    }

    private void setAuthorizationHeader(HttpHeaders httpHeaders) {
        httpHeaders.set(AUTHORIZATION, this.tokenService.getAuthorizationHeaderValue());
    }
}
public class TokenService {

    private static final String SPN = "MyServicePrincipleName";
    private static final String NEGOTIATE_PREFIX = "Negotiate ";

    //See https://github.com/Waffle/waffle/blob/master/Source/JNA/waffle-jna/src/main/java/waffle/windows/auth/impl/WindowsSecurityContextImpl.java 
    @Autowired
    private WindowsSecurityContextImpl clientContext;

    public boolean initializeClientContext(String continueTokenAsBase64String) {
        ManagedSecBufferDesc continueToken = new ManagedSecBufferDesc(Sspi.SECBUFFER_TOKEN,
                Base64.getDecoder().decode(continueTokenAsBase64String));
        try {
            clientContext.initialize(clientContext.getHandle(), continueToken, SPN);
            return true;
        } catch (RuntimeException e) {
            return false;
        }
    }

    public String getAuthorizationHeaderValue() {
        return NEGOTIATE_PREFIX + Base64.getEncoder().encodeToString(clientContext.getToken());
    }

    public String getContinueToken(HttpHeaders httpHeader) {
        if (httpHeader.containsKey("WWW-Authenticate")) {
            String headerValue = httpHeader.get("WWW-Authenticate").get(0);
            return headerValue.substring(NEGOTIATE_PREFIX.length());
        }
        return "";
    }
}

Это работает, только если для POOL_MAX_CONNECTIONS HttpClient установлено значение 1 HttpClient.create(ConnectionProvider.create("CP", 1));. Потому что continueToken должен быть отправлен через то же соединение. В противном случае сервер отклонит его. Но теперь мне нужно увеличить ограничение соединения из-за поддержки SSL.

Как мне заставить это работать с любым размером POOL_MAX_CONNECTIONS?

Как мне указать exchangeFunction.exchange(continueChallangeRequest);, чтобы использовать то же соединение оригинал ClientRequest request используется?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...