web-dev-qa-db-ja.com

リクエストごとのApacheHTTPクライアント4.3認証情報

私はダイジェスト認証の例を次の場所で調べています。

http://hc.Apache.org/httpcomponents-client-4.3.x/examples.html

私のシナリオでは、HTTPリクエストを発行するスレッドがいくつかあり、それぞれが独自の資格情報のセットで認証される必要があります。さらに、この質問はおそらくApache HTTPクライアント4.3以降に非常に固有であり、4.2はおそらく別の方法で認証を処理しますが、私自身はチェックしていません。そうは言っても、実際の問題があります。

1つのクライアントインスタンス(クラスの静的メンバー、つまりスレッドセーフ)のみを使用し、複数の同時要求をサポートする接続マネージャーを提供したいと思います。重要なのは、リクエストごとに異なる資格情報が提供され、httpクライアントの構築時に資格情報プロバイダーが設定されているため、リクエストごとに資格情報を割り当てる方法がわかりません。上記のリンクから:

[...]

    HttpHost targetHost = new HttpHost("localhost", 80, "http");
    CredentialsProvider credsProvider = new BasicCredentialsProvider();
    credsProvider.setCredentials(
            new AuthScope(targetHost.getHostName(), targetHost.getPort()),
            new UsernamePasswordCredentials("username", "password"));
    CloseableHttpClient httpclient = HttpClients.custom()
            .setDefaultCredentialsProvider(credsProvider).build();

[...]

チェック:

http://hc.Apache.org/httpcomponents-client-ga/tutorial/html/authentication.html#d5e6

ポイント4.4のコードサンプル(seek4.4。HTTP認証と実行コンテキスト)は、HttpClientContextに認証キャッシュと資格情報プロバイダーが与えられていると言っているようです。その後、HTTPリクエストに渡されます。その隣でリクエストが実行され、クライアントはHTTPリクエストでホストによる資格情報フィルタリングを取得するようです。言い換えると、コンテキスト(またはキャッシュ)に現在のHTTPリクエストのターゲットホストの有効な資格情報がある場合、彼はそれらを使用します。私にとっての問題は、異なるスレッドが同じホストに対して異なる要求を実行することです。

HTTPリクエストごとにカスタム認証情報を提供する方法はありますか?

よろしくお願いします! :)

私にとっての問題は、異なるスレッドが同じホストに対して異なる要求を実行することです。

なぜこれが問題になるのですか?スレッドごとに異なるHttpContextインスタンスを使用する限り、それらのスレッドの実行コンテキストは完全に独立しています。

CloseableHttpClient httpclient = HttpClients.createDefault();
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials("user:pass"));
HttpClientContext localContext = HttpClientContext.create();
localContext.setCredentialsProvider(credentialsProvider);

HttpGet httpget = new HttpGet("http://localhost/");

CloseableHttpResponse response = httpclient.execute(httpget, localContext);
try {
    EntityUtils.consume(response.getEntity());
} finally {
    response.close();
}
13
ok2c

同様の問題があります。

NTLMで認証された単一のシステムユーザーでn回サービスを呼び出す必要があります。複数のスレッドを使用してこれを実行したいと思います。私が思いついたのは、デフォルトの資格情報プロバイダーを使用せずに単一のHTTPClientを作成することです。リクエストを実行する必要がある場合、(特定のスレッドで)リクエストを実行するメソッドに挿入されたCredentialProviderFactoryを使用します。これを使用して、新しいCredentialsProviderを取得し、これをコンテキスト(スレッドで作成)に配置します。次に、オーバーロードexecute(method, context)を使用してクライアントのexecuteメソッドを呼び出します。

class MilestoneBarClient implements IMilestoneBarClient {

private static final Logger log = LoggerFactory.getLogger(MilestoneBarClient.class);
private MilestoneBarBuilder builder;
private CloseableHttpClient httpclient;
private MilestoneBarUriBuilder uriBuilder;
private ICredentialsProviderFactory credsProviderFactory;


MilestoneBarClient(CloseableHttpClient client, ICredentialsProviderFactory credsProviderFactory, MilestoneBarUriBuilder uriBuilder) {
    this(client, credsProviderFactory, uriBuilder, new MilestoneBarBuilder());
}

MilestoneBarClient(CloseableHttpClient client, ICredentialsProviderFactory credsProviderFactory, MilestoneBarUriBuilder uriBuilder, MilestoneBarBuilder milestoneBarBuilder) {
    this.credsProviderFactory = credsProviderFactory;
    this.uriBuilder = uriBuilder;
    this.builder = milestoneBarBuilder;
    this.httpclient = client;
}

// This method is called by multiple threads
@Override
public MilestoneBar get(String npdNumber) {
    log.debug("Asking milestone bar info for {}", npdNumber);

    try {
        String url = uriBuilder.getPathFor(npdNumber);
        log.debug("Building request for URL {}", url);
        HttpClientContext localContext = HttpClientContext.create();
        localContext.setCredentialsProvider(credsProviderFactory.create());

        HttpGet httpGet = new HttpGet(url);

        long start = System.currentTimeMillis();
        try(CloseableHttpResponse resp = httpclient.execute(httpGet, localContext)){
[...]

いくつかの理由でエラーが発生することがありますが、これはNTLMCredentialsの問題だと思います(スレッドセーフではありません...)。

あなたの場合、作成を渡す代わりに、ファクトリをgetメソッドに渡すことができます。

0
Adhara