10

4.3憑據我一直有在看的摘要式身份驗證例如:Apache的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被授予auth緩存和credentinti als提供程序,然後傳遞給HTTP請求。在它旁邊執行請求,看起來客戶端將在HTTP請求中獲取由主機進行的憑據過濾。換句話說:如果上下文(或緩存)具有當前HTTP請求的目標主機的有效憑證,他將使用它們。對我來說,問題是不同的線程會對同一個主機執行不同的請求。

有什麼辦法可以爲每個HTTP請求提供自定義憑據嗎?

在此先感謝您的時間! :)

+0

可能重複[使用httpclient 4.x驗證單個請求](http://stackoverflow.com/questions/2516345/authenticating-a-single-request-with-httpclient-4x) – davidwebster48

回答

13

我的問題是,不同的線程將執行不同的請求到同一主機。

爲什麼這應該是一個問題?只要你每個線程使用不同的HttpContext實例,這些線程的執行上下文將是完全indepenent

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(); 
} 
+0

對不起,我的問題是不健康的: _對我來說問題是不同的線程**具有不同的憑據**每個**將執行對同一主機的請求。因此,對於所有線程只有一個客戶端和一個憑證提供程序實例每個線程將放置它的憑證)和每個線程一個上下文,(唯一)客戶端如何知道每個線程使用什麼憑證? 感謝您的時間提前! –

+0

@FranciscoCarriedoScher:我不知道我明白你在這裏遇到的困難。絕對沒有什麼能夠阻止你爲每個線程/上下文設置一個單獨的憑證提供程序 – oleg

+0

困難在於爲所有線程保存一個CredentialsProvider(因爲它似乎在內部準備好管理一組憑證),但最終似乎至少BasicCredentialsProvider每個實例只管理一個憑證。 因此,爲每個線程使用新的憑據提供程序實例似乎是一種方式,您的示例工作正常。 –

0

我有一個類似的問題。

我必須通過單一系統用戶調用n次服務,並使用NTLM進行身份驗證。我想用多個線程來做到這一點。 我想到的是創建一個沒有默認憑據提供者的HTTPClient。當需要執行請求時,我將注入的CredentialProviderFactory用於執行請求的方法(在特定的線程中)。使用這個我得到一個全新的CredentialsProvider,並把它放入一個Context(在線程中創建)。 然後我使用過載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方法而不是傳入創建。

相關問題