閱讀700 返回首頁    go 阿裏雲 go 技術社區[雲棲]


《HttpClient官方文檔》HTTP驗證4.4-4.7

4.4 HTTP驗證和執行上下文

HttpClient依賴於AuthState類來追蹤驗證進程的狀態的詳細信息。HttpClient在執行HTTP請求執行時,創建AuthState的兩個實例:一個對目標主機認證,另外一個用於代理認證。一旦目標主機或者代理要求用戶驗證,對應的AuthState實例將會在驗證過程中被AuthScope,AuthScheme和Crednetials填充。這個AuthState可以被檢查用於找出哪種類型要求驗證,是否對應的AuthScheme被找到,以及憑證提供者可以找到在給定的驗證範圍內找到用戶憑證。


在HTTP請求過程中HttpClient添加了以下的驗證關係對象到執行上下文中:

  • Lookup 實例代表實際的驗證方案注冊。這個屬性值在本地上下文中優先與默認值被設置。
  • CredentialsProvider實例代表實際的憑證提供者。這個屬性值本地上下文中優先與默認值被設置。
  • AuthState實例代表實際的目標驗證狀態。這個屬性值本地上下文中優先與默認值被設置。
  • AuthState實例代表實際的代理驗證狀態。這個屬性值本地上下文中優先與默認值被設置。
  • AuthCache實例代表實際的驗證數據緩存。這個屬性值本地上下文中優先與默認值被設置。

這個本地的HttpContext對象可以在請求執行之前定製HTTP驗證上下文或者在請求被執行後檢查它的狀態:

CloseableHttpClient httpclient = <...>
CredentialsProvider credsProvider = <...>
Lookup<AuthSchemeProvider> authRegistry = <...>
AuthCache authCache = <...>
HttpClientContext context = HttpClientContext.create();
context.setCredentialsProvider(credsProvider);
context.setAuthSchemeRegistry(authRegistry);
context.setAuthCache(authCache);
HttpGet httpget = new HttpGet("https://somehost/");
CloseableHttpResponse response1 = httpclient.execute(httpget, context);
<...>
AuthState proxyAuthState = context.getProxyAuthState();
System.out.println("Proxy auth state: " + proxyAuthState.getState());
System.out.println("Proxy auth scheme: " + proxyAuthState.getAuthScheme());
System.out.println("Proxy auth credentials: " + proxyAuthState.getCredentials());
AuthState targetAuthState = context.getTargetAuthState();
System.out.println("Target auth state: " + targetAuthState.getState());
System.out.println("Target auth scheme: " + targetAuthState.getAuthScheme());
System.out.println("Target auth credentials: " + targetAuthState.getCredentials());

4.5 驗證數據緩存

從4.1版本開始HttpClient自動緩存驗證成功的主機的信息。請注意為了使緩存的驗證數據從一個請求傳播到另外一個請求上,必須使用相同的上下文來執行相關的邏輯請求。如果執行上下文超出了範圍,驗證數據將會很快丟失。

4.6 搶占式驗證

HttpClient 不支持搶占試驗證因為如果錯誤使用搶占式驗證會導致明顯的安全問題,比如明文發送用戶憑證到第三方沒有驗證的組織。除此之外用戶被期望在他們自己的應用環境中自己來評估搶占式驗證的潛在好處和安全風險。
盡管如此可以通過配置HttpClient預填充驗證數據到緩衝中來實現搶占式驗證。
CloseableHttpClient httpclient = <…>

HttpHost targetHost = new HttpHost("localhost", 80, "http");
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(
        new AuthScope(targetHost.getHostName(), targetHost.getPort()),
        new UsernamePasswordCredentials("username", "password"));

// Create AuthCache instance
AuthCache authCache = new BasicAuthCache();
// Generate BASIC scheme object and add it to the local auth cache
BasicScheme basicAuth = new BasicScheme();
authCache.put(targetHost, basicAuth);

// Add AuthCache to the execution context
HttpClientContext context = HttpClientContext.create();
context.setCredentialsProvider(credsProvider);
context.setAuthCache(authCache);
HttpGet httpget = new HttpGet("/");
for (int i = 0; i < 3; i++) {
    CloseableHttpResponse response = httpclient.execute(
            targetHost, httpget, context);
    try {
        HttpEntity entity = response.getEntity();
    } finally {
        response.close();
    }
}

4.7 NTLM驗證

自從4.1HttpClient版本對NTLMv1, NTLMv2, and NTLM2會話驗證提供完全的支持。外部的NTML引擎比如由Samba項目開發的JCIFS庫作為其Windows互操作性程序套件的一部分仍然可以被使用。

4.7.1 NTLM連接持久化

NTLM驗證方案比標準的Basic和Digest方案要明顯消耗更多的計算性能。這也許是微軟選擇使NTLM驗證方案狀態話的主要原因。隻要驗證成功了,這個用戶的標誌會和它整個連接的壽命相關。NTLM有狀態的特性使連接持久化更加複雜,一個明顯的原因:連接持久化的NTLM不能被不同的用戶標識進行重用。無論如何在同一個會話中邏輯相關的請求使用相同的執行上下文來保證它們意識到當前用戶的身份。否則HttpClient將會針對每一個NTLM保護請求的每一個Http請求創建一個新的HTTP連接。對於狀態話的HTTP請求的詳細討論請參考這個頁麵
由於NTLM是狀態話的,它一般推薦使用相對便宜的方式來觸發NTLM驗證,比如GET或者HEAD,以及複用相同的連接來執行更加昂貴的操作,特別是包含了請求實體的比如POST或者PUT。

CloseableHttpClient httpclient = <...>
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(AuthScope.ANY,
        new NTCredentials("user", "pwd", "myworkstation", "microsoft.com"));

HttpHost target = new HttpHost("www.microsoft.com", 80, "http");

// Make sure the same context is used to execute logically related requests
HttpClientContext context = HttpClientContext.create();
context.setCredentialsProvider(credsProvider);

// Execute a cheap method first. This will trigger NTLM authentication
HttpGet httpget = new HttpGet("/ntlm-protected/info");
CloseableHttpResponse response1 = httpclient.execute(target, httpget, context);
try {
    HttpEntity entity1 = response1.getEntity();
} finally {
    response1.close();
}

// Execute an expensive method next reusing the same context (and connection)
HttpPost httppost = new HttpPost("/ntlm-protected/form");
httppost.setEntity(new StringEntity("lots and lots of data"));
CloseableHttpResponse response2 = httpclient.execute(target, httppost, context);
try {
    HttpEntity entity2 = response2.getEntity();
} finally {
    response2.close();
}

轉載自 並發編程網 - ifeve.com

最後更新:2017-05-19 12:04:27

  上一篇:go  如何安裝 pandom : 一個針對 Linux 的真隨機數生成器
  下一篇:go  如何在 Linux 中使用 Asciinema 進行錄製和回放終端會話