Я написал функцию 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
используется?