[英]Spring WebClient Windows NTLM Authentication
我找不到任何好的示例或文檔來清楚地解釋這一點。 我可以成功地使用(舊的)RestTemplate 進行身份驗證:
HttpClientBuilder httpClient = HttpClients.custom();
BasicCredentialsProvider provider = new BasicCredentialsProvider();
Credentials cred = new NTCredentials("my-user", "my-password", null, "my-domain");
provider.setCredentials(AuthScope.ANY, cred);
httpClient.setDefaultCredentialsProvider(provider);
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.httpClient = httpClient.build();
RestTemplate restTemplate = new RestTemplate(request);
restTemplate.getForEntity("https://my.url.com", String.class)
我一直無法找到將NTCredentials
(或Credentials
)傳遞給 WebClient 的方法,已經嘗試過
WebClient client = WebClient.builder()
.filter(ExchangeFilterFunctions.basicAuthentication("user", "password"))
.build();
還
WebClient client = WebClient.builder().build();
client.get().headers(h -> h.setBasicAuth("user", "password"))...
但是這兩種方法都不適用於 WebClient
問題:
我最近一直在研究 Spring WebClient 的 NTLM。 首先,我嘗試使用 Apache HttpClient,但沒有得到任何響應。 我沒有進一步調查原因...
因為無論如何我都想使用 .netty HttpClient,所以我使用 JCIFS 實現實現了自己的ExchangeFilterFunction
(與 Apache HttpClient 使用的相同)。 類似於:
public final class NtlmAuthorizedClientExchangeFilterFunction implements ExchangeFilterFunction {
private final NtlmPasswordAuthentication ntlmPasswordAuthentication;
private final boolean doSigning;
public NtlmAuthorizedClientExchangeFilterFunction(String domain, String username, String password, boolean doSigning, int lmCompatibility) {
this.ntlmPasswordAuthentication = new NtlmPasswordAuthentication(domain, username, password);
this.doSigning = doSigning;
System.setProperty("jcifs.smb.lmCompatibility", Integer.toString(lmCompatibility));
}
@Override
public Mono<ClientResponse> filter(final ClientRequest request, final ExchangeFunction next) {
NtlmContext ntlmContext = new NtlmContext(ntlmPasswordAuthentication, doSigning);
try {
return next.exchange(addNtlmHeader(request, ntlmContext.initSecContext(new byte[0], 0, 0)))
.publishOn(Schedulers.single()) // this is necessary to make sure that the requests are processed sequential and thus http keep alive is working
.flatMap(clientResponse -> {
List<String> ntlmAuthHeaders = getNtlmAuthHeaders(clientResponse);
if (ntlmAuthHeaders.isEmpty()) return Mono.error(...);
String ntlmHeader = ntlmAuthHeaders.get(0);
if (ntlmHeader.length() <= 5) return Mono.error(...);
try {
byte[] type2 = Base64.decode(ntlmHeader.substring(5));
return next.exchange(addNtlmHeader(request, ntlmContext.initSecContext(type2, 0, type2.length)));
} catch (IOException e) {
return Mono.error(...);
}
});
} catch (SmbException e) {
return Mono.error(...);
}
}
@NotNull
private static List<String> getNtlmAuthHeaders(ClientResponse clientResponse) {
List<String> wwwAuthHeaders = clientResponse.headers().header(HttpHeaders.WWW_AUTHENTICATE);
List<String> ntlmAuthHeaders = wwwAuthHeaders.stream().filter(h -> h.startsWith("NTLM")).sorted(Comparator.comparingInt(String::length)).collect(Collectors.toList());
return ntlmAuthHeaders;
}
private ClientRequest addNtlmHeader(ClientRequest clientRequest, byte[] ntlmPayload) {
ClientRequest.Builder request = ClientRequest
.from(clientRequest)
.header(HttpHeaders.AUTHORIZATION, "NTLM ".concat(Base64.encode(ntlmPayload)));
return request.build();
}
你的第二個問題我沒有答案。 我的系統是 Linux。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.