如何使用 JAX-RS 2.0 兼容的 RESTEasy 客户端 API 启用 NTLM 身份验证?

How to enable NTLM authentication with JAX-RS 2.0 compliant RESTEasy client API?

默认情况下,使用 RESTEasy 客户端 API 向需要 NTLM 身份验证的安全资源发送请求会导致状态为 401 Unauthorized 和 header WWW-Authenticate: NTLM 的 HTTP 响应。

如何使用 RESTEasy 客户端启用 NTLM 身份验证 API 以及如何提供凭据?

已有相关问题提供了有用的答案:

它们有些过时(使用已弃用的和遗留的 API)并且要求略有不同。

在使用 JAX-RS 2.0 兼容的 RESTEasy 客户端从 Java 中使用 ASP.NET Web API 托管在 Internet Information Services (IIS) 上的 REST 服务的任务中挣扎之后API,我想在回答这个问题时分享我的经验。

RESTEasy 客户端 API 的身份验证由封装的 ClientHttpEngine 完成。我在这个答案中提到的版本 3.0.19.Final 符合 JAX-RS 2.0 并附带两个实现。两者都可以进行 NTLM 身份验证。

使用默认值ApacheHttpClient4Engine

即使它是默认引擎,您也需要设置一个自定义实例来提供凭据。首先 Credentials have to be added to a CredentialsProvider with respect to an concrete AuthScope. The next step is to set them up on a HttpClientContext 然后需要再次提供给引擎。

Credentials credentials = new NTCredentials("user", "password", "workstation", "domain");
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(
  new AuthScope(null, AuthScope.ANY_PORT, AuthScope.ANY_REALM, AuthSchemes.NTLM)
  , credentials
);
HttpClientContext httpContext = HttpClientContext.create();
httpContext.setCredentialsProvider(credentialsProvider);
try (CloseableHttpClient httpClient = HttpClientBuilder.create().build();) {
  ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(httpClient, httpContext);
  ResteasyClient client = new ResteasyClientBuilder().httpEngine(engine).build();
  // work with the client
}

使用URLConnectionEngine

此引擎在自定义子类中使用 HttpURLConnection which somehow invokes an Authenticator to do authentication. To provide the credentials you must override getPasswordAuthentication 并将其注册为默认值。

public class NTLMAuthenticator extends Authenticator {
  @Override
  protected PasswordAuthentication getPasswordAuthentication() {
    return new PasswordAuthentication("domain\user", "password".toCharArray());
  }
}
Authenticator.setDefault(new NTLMAuthenticator());
ResteasyClient client =
  new ResteasyClientBuilder().httpEngine(new URLConnectionEngine()).build();
// work with the client
client.close();

资源