HttpClient4.3教程 第四章 HTTP認證

HttpClient4.3教程 第四章 HTTP認證

HttpClient既支持HTTP標準規範定義的認證模式,又支持一些普遍使用的非標準認證模式,好比NTLM和SPNEGO。java

4.1.用戶憑證

任何用戶認證的過程,都須要一系列的憑證來肯定用戶的身份。最簡單的用戶憑證能夠是用戶名和密碼這種形式。UsernamePasswordCredentials這個類能夠用來表示這種狀況,這種憑據包含明文的用戶名和密碼。
這個類對於HTTP標準規範中定義的認證模式來講已經足夠了。 windows

UsernamePasswordCredentials creds = new UsernamePasswordCredentials("user", "pwd");    System.out.println(creds.getUserPrincipal().getName());    System.out.println(creds.getPassword());

上述代碼會在控制檯輸出: 緩存

user    pwd

NTCredentials是微軟的windows系統使用的一種憑據,包含username、password,還包括一系列其餘的屬性,好比用戶所在的域名。在Microsoft Windows的網絡環境中,同一個用戶能夠屬於不一樣的域,因此他也就有不一樣的憑據。 安全

NTCredentials creds = new NTCredentials("user", "pwd", "workstation", "domain");    System.out.println(creds.getUserPrincipal().getName());    System.out.println(creds.getPassword());

上述代碼輸出:服務器

DOMAIN/user    pwd

4.2. 認證方案

AutoScheme接口表示一個抽象的面向挑戰/響應的認證方案。一個認證方案要支持下面的功能: 網絡

  • 客戶端請求服務器受保護的資源,服務器會發送過來一個chanllenge(挑戰),認證方案(Authentication scheme)須要解析、處理這個挑戰
  • 爲processed challenge提供一些屬性值:認證方案的類型,和此方案須要的一些參數,這種方案適用的範圍
  • 使用給定的受權信息生成受權字符串;生成http請求,用來響應服務器發送來過的受權challenge

請注意:一個認證方案多是有狀態的,由於它可能涉及到一系列的挑戰/響應。
HttpClient實現了下面幾種AutoScheme: dom

  • Basic: Basic認證方案是在RFC2617號文檔中定義的。這種受權方案用明文來傳輸憑證信息,因此它是不安全的。雖然Basic認證方案自己是不安全的,可是它一旦和TLS/SSL加密技術結合起來使用,就徹底足夠了。
  • Digest: Digest(摘要)認證方案是在RFC2617號文檔中定義的。Digest認證方案比Basic方案安全多了,對於那些受不了Basic+TLS/SSL傳輸開銷的系統,digest方案是個不錯的選擇。
  • NTLM: NTLM認證方案是個專有的認證方案,由微軟開發,而且針對windows平臺作了優化。NTLM被認爲比Digest更安全。
  • SPNEGO: SPNEGO(Simple and Protected GSSAPI Negotiation Mechanism)是GSSAPI的一個「僞機制」,它用來協商真正的認證機制。SPNEGO最明顯的用途是在微軟的HTTP協商認證機制拓展上。可協商的子機制包括NTLM、Kerberos。目前,HttpCLient只支持Kerberos機制。(原文:The negotiable sub-mechanisms include NTLM and Kerberos supported by Active Directory. At present HttpClient only supports the Kerberos sub-mechanism.)

4.3. 憑證 provider

憑證providers旨在維護一套用戶的憑證,當須要某種特定的憑證時,providers就應該能產生這種憑證。認證的具體內容包括主機名、端口號、realm name和認證方案名。當使用憑據provider的時候,咱們能夠很模糊的指定主機名、端口號、realm和認證方案,不用寫的很精確。由於,憑據provider會根據咱們指定的內容,篩選出一個最匹配的方案。
只要咱們自定義的憑據provider實現了CredentialsProvider這個接口,就能夠在HttpClient中使用。默認的憑據provider叫作BasicCredentialsProvider,它使用java.util.HashMapCredentialsProvider進行了簡單的實現。 ide

CredentialsProvider credsProvider = new BasicCredentialsProvider();    credsProvider.setCredentials(    new AuthScope("somehost", AuthScope.ANY_PORT),    new UsernamePasswordCredentials("u1", "p1"));    credsProvider.setCredentials(    new AuthScope("somehost", 8080),    new UsernamePasswordCredentials("u2", "p2"));    credsProvider.setCredentials(    new AuthScope("otherhost", 8080, AuthScope.ANY_REALM, "ntlm"),    new UsernamePasswordCredentials("u3", "p3"));    System.out.println(credsProvider.getCredentials(    new AuthScope("somehost", 80, "realm", "basic")));    System.out.println(credsProvider.getCredentials(    new AuthScope("somehost", 8080, "realm", "basic")));    System.out.println(credsProvider.getCredentials(    new AuthScope("otherhost", 8080, "realm", "basic")));    System.out.println(credsProvider.getCredentials(    new AuthScope("otherhost", 8080, null, "ntlm")));

上面代碼輸出: 優化

[principal: u1]    [principal: u2]    null    [principal: u3]

4.4.HTTP受權和執行上下文

HttpClient依賴AuthState類去跟蹤認證過程當中的狀態的詳細信息。在Http請求過程當中,HttpClient建立兩個AuthState實例:一個用於目標服務器認證,一個用於代理服務器認證。若是服務器或者代理服務器須要用戶的受權信息,AuthScopeAutoScheme和認證信息就會被填充到兩個AuthScope實例中。經過對AutoState的檢測,咱們能夠肯定請求的受權類型,肯定是否有匹配的AuthScheme,肯定憑據provider根據指定的受權類型是否成功生成了用戶的受權信息。
在Http請求執行過程當中,HttpClient會向執行上下文中添加下面的受權對象: 加密

  • Lookup對象,表示使用的認證方案。這個對象的值能夠在本地上下文中進行設置,來覆蓋默認值。
  • CredentialsProvider對象,表示認證方案provider,這個對象的值能夠在本地上下文中進行設置,來覆蓋默認值。
  • AuthState對象,表示目標服務器的認證狀態,這個對象的值能夠在本地上下文中進行設置,來覆蓋默認值。
  • AuthState對象,表示代理服務器的認證狀態,這個對象的值能夠在本地上下文中進行設置,來覆蓋默認值。
  • AuthCache對象,表示認證數據的緩存,這個對象的值能夠在本地上下文中進行設置,來覆蓋默認值。

咱們能夠在請求執行前,自定義本地HttpContext對象來設置須要的http認證上下文;也能夠在請求執行後,再檢測HttpContext的狀態,來查看受權是否成功。

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("http://www.yeetrack.com/");    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仍是容許咱們經過配置來啓用搶先認證,方法是提早填充認證信息緩存到上下文中,這樣,以這個上下文執行的方法,就會使用搶先認證。

繼續閱讀→

相關文章
相關標籤/搜索