10

당 4.3 자격 증명이 나는에서 다이제스트 인증의 예를 살펴 가지고 있었다 : 내 시나리오에서아파치 HTTP 클라이언트가 요청

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

을가 HTTP 요청을 발행하는 여러 스레드가 있고 그들 각각이 있어야한다 고유 한 자격 증명 세트로 인증됩니다. 또한,이 질문은 Apache HTTP 클라이언트 4.3 이후 버전에서 매우 구체적이라고 생각해보십시오. 4.2는 아마 다른 방법으로 인증을 처리합니다.하지만 직접 확인하지는 않았습니다. 즉, 실제 질문이 나온다.

하나의 클라이언트 인스턴스 (스레드의 안전성을 갖는 클래스의 정적 멤버)를 사용하고 여러 동시 요청을 지원하는 연결 관리자를 제공하려고합니다. 요점은 각 요청마다 다른 자격 증명을 제공 할 것이고 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#d5e600

점 4.4의 코드 예제 (을 추구 4.4 HTTP 인증 및 실행 컨텍스트)은 HttpClientContext에 인증 캐시와 credenti가 주어 졌다고합니다. 공급자가 HTTP 요청에 전달됩니다. 그 옆에 요청이 실행되고 클라이언트가 HTTP 요청에서 호스트에 의해 자격 증명 필터링을받는 것으로 보입니다. 즉, 컨텍스트 (또는 캐시)에 현재 HTTP 요청의 대상 호스트에 대한 유효한 자격 증명이있는 경우이를 사용합니다. 문제는 다른 스레드가 동일한 호스트에 다른 요청을 수행한다는 것입니다.

HTTP 요청마다 사용자 지정 자격 증명을 제공 할 수있는 방법이 있습니까?

미리 감사드립니다. :)

+0

[httpclient 4.x로 단일 요청 인증] 가능한 복제본 (http://stackoverflow.com/questions/2516345/authenticating-a-single-request-with-httpclient-4-x) – davidwebster48

답변

13

나를위한 문제는 다른 스레드가 동일한 호스트에 다른 요청을 수행한다는 것입니다.

왜 이것이 문제입니까? 스레드마다 다른 HttpContext 인스턴스를 사용하는 한 이러한 스레드의 실행 컨텍스트는 완전히 독립적 일 것입니다.

+0

죄송합니다, 내 질문이 정확하지 않습니다. _ 문제는 각기 다른 자격 증명을 가진 서로 다른 스레드 **가 동일한 호스트에 대한 요청을 수행한다는 것입니다. _ 따라서 모든 클라이언트에 대해 하나의 클라이언트와 하나의 자격 증명 공급자 인스턴스 만 있으면 각 스레드는 자격 증명에 배치됩니다) 및 스레드 당 하나의 컨텍스트, (전용) 클라이언트가 각 스레드에 사용할 자격 증명을 어떻게 알 수 있습니까 ??? 미리 감사드립니다. –

+0

@FranciscoCarriedoScher : 여기에있는 어려움을 잘 모르겠다. 스레드/컨텍스트마다 별도의 자격 증명 공급자가 없게하는 것은 전혀 없습니다. – oleg

+0

어려움은 모든 스레드에 대해 단일 CredentialsProvider를 보유하는 것입니다 (내부적으로 자격 증명 집합을 관리 할 준비가되어있는 것처럼 보이지만). 최소한 BasicCredentialsProvider는 인스턴스 당 하나의 자격 증명 만 관리합니다. 그래서 스레드마다 새 자격 증명 공급자 인스턴스를 사용하는 것이 좋습니다. 예제가 제대로 작동합니다. –

0

비슷한 문제가 있습니다.

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 문제 (thread-safe ...가 아님)가있는 것 같습니다.

귀하의 경우, 생성을 전달하는 대신 get 메소드로 팩토리를 전달할 수 있습니다.