HttpClient既支持HTTP標準規範定義的認證模式,又支持一些普遍使用的非標準認證模式,好比NTLM和SPNEGO。java
任何用戶認證的過程,都須要一系列的憑證來肯定用戶的身份。最簡單的用戶憑證能夠是用戶名和密碼這種形式。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
AutoScheme
接口表示一個抽象的面向挑戰/響應的認證方案。一個認證方案要支持下面的功能: 網絡
請注意:一個認證方案多是有狀態的,由於它可能涉及到一系列的挑戰/響應。
HttpClient實現了下面幾種AutoScheme
: dom
憑證providers旨在維護一套用戶的憑證,當須要某種特定的憑證時,providers就應該能產生這種憑證。認證的具體內容包括主機名、端口號、realm name和認證方案名。當使用憑據provider的時候,咱們能夠很模糊的指定主機名、端口號、realm和認證方案,不用寫的很精確。由於,憑據provider會根據咱們指定的內容,篩選出一個最匹配的方案。
只要咱們自定義的憑據provider實現了CredentialsProvider
這個接口,就能夠在HttpClient中使用。默認的憑據provider叫作BasicCredentialsProvider
,它使用java.util.HashMap
對CredentialsProvider
進行了簡單的實現。 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]
HttpClient依賴AuthState
類去跟蹤認證過程當中的狀態的詳細信息。在Http請求過程當中,HttpClient建立兩個AuthState
實例:一個用於目標服務器認證,一個用於代理服務器認證。若是服務器或者代理服務器須要用戶的受權信息,AuthScope
、AutoScheme
和認證信息就會被填充到兩個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.1開始,HttpClient就會自動緩存驗證經過的認證信息。可是爲了使用這個緩存的認證信息,咱們必須在同一個上下文中執行邏輯相關的請求。一旦超出該上下文的做用範圍,緩存的認證信息就會失效。
HttpClient默認不支持搶先認證,由於一旦搶先認證被誤用或者錯用,會致使一系列的安全問題,好比會把用戶的認證信息以明文的方式發送給未受權的第三方服務器。所以,須要用戶本身根據本身應用的具體環境來評估搶先認證帶來的好處和帶來的風險。
即便如此,HttpClient仍是容許咱們經過配置來啓用搶先認證,方法是提早填充認證信息緩存到上下文中,這樣,以這個上下文執行的方法,就會使用搶先認證。