如何使用HttpClient認證機制

1.服務器認證(Server Authentication)HttpClient處理服務器認證幾乎是透明的,僅須要開發人員提供登陸信息(login credentials)。登陸信息保存在HttpState類的實例中,能夠經過 setCredentials(String realm, Credentials cred)和getCredentials(String realm)來獲取或設置。HttpClient內建的自動認證,能夠經過HttpMethod類的setDoAuthentication(boolean doAuthentication)方法關閉,並且此次關閉隻影響HttpMethod當前的實例。html

1.1搶先認證(Preemptive Authentication)在這種模式時,HttpClient會主動將basic認證應答信息傳給服務器,即便在某種狀況下服務器可能返回認證失敗的應答,這樣作主要是爲了減小鏈接的創建。使用該機制以下所示:
client.getParams().setAuthenticationPreemptive(true);
搶先認證模式也提供對於特定目標或代理的缺省認證。若是沒有提供缺省的認證信息,則該模式會失效。
Credentials defaultcreds = new UsernamePasswordCredentials("username", "password");client.getState().setCredentials(new AuthScope("myhost", 80, AuthScope.ANY_REALM), defaultcreds);
Httpclient實現的搶先認證遵循rfc2617.
A client SHOULD assume that all paths at or deeper than the depth of the last symbolic element in the path field of the Request-URI also are within the protection space specified by the Basic realm value of the current challenge. A client MAY preemptively send the corresponding Authorization header with requests for resources in that space without receipt of another challenge from the server. Similarly, when a client sends a request to a proxy, it may reuse a userid and password in the Proxy-Authorization header field without receiving another challenge from the proxy server.
1.2服務器認證的安全方面考慮當須要與不被信任的站點或web應用通訊時,應該謹慎使用缺省的認證機制。當啓動(activate)搶先認證模式,或者認證中沒有明確給出認證域,主機的HttpClient將使用缺省的認證機制去試圖得到目標站點的受權。若是你提供的認證信息是敏感的,你應該指定認證域。不推薦將認證域指定爲AuthScope.ANY。(只有在debugging狀況下,才使用)
// To be avoided unless in debug modeCredentials defaultcreds = new UsernamePasswordCredentials("username", "password");client.getState().setCredentials(AuthScope.ANY, defaultcreds); web

2.代理認證(proxy authentication)  除了登陸信息需單獨存放之外,代理認證與服務器認證幾乎一致。用 setProxyCredentials(String realm, Credentials cred)和 getProxyCredentials(String realm)設、取登陸信息。安全

3.認證方案(authentication schemes)服務器

3.1 Basic是HTTP中規定最先的也是最兼容的方案,遺憾的是也是最不安全的一個方案,由於它以明碼傳送用戶名和密碼。它要求一個UsernamePasswordCredentials實例,能夠指定服務器端的訪問空間或採用默認的登陸信息。 網絡

3.2 Digest是在HTTP1.1 中增長的一個方案,雖然不如Basic獲得的軟件支持多,但仍是有普遍的使用。less

Digest方案比Basic方案安全得多,因它根本就不經過網絡傳送實際的密碼,傳送的是利用這個密碼對從服務器傳來的一個隨機數(nonce)的加密串。它要求一個UsernamePasswordCredentials實例,能夠指定服務器端的訪問空間或採用默認的登陸信息。 ide

3.3 NTLM這是HttpClient支持的最複雜的認證協議。它Microsoft設計的一個私有協議,沒有公開的規範說明。一開始因爲設計的缺陷,NTLM的安全性比 Digest差,後來通過一個ServicePack補丁後,安全性則比較Digest高。NTLM須要一個NTCredentials實例。 注意,因爲NTLM不使用訪問空間(realms)的概念,HttpClient利用服務器的域名做訪問空間的名字。還須要注意,提供給NTCredentials的用戶名,不要用域名的前綴 - 如: "adrian" 是正確的,而 "DOMAIN\adrian" 則是錯的。NTLM認證的工做機制與basic和digest有很大的差異。這些差異通常由HttpClient處理,但理解這些差異有助避免在使用NTLM認證時出現錯誤。[1] 從HttpClientAPI的角度來看,NTLM與其它認證方式同樣的工做,差異是須要提供'NTCredentials'實例而不是'UsernamePasswordCredentials'(其實,前者只是擴展了後者)[2] 對NTLM認證,訪問空間是鏈接到的機器的域名,這對多域名主機會有一些麻煩。只有HttpClient鏈接中指定的域名纔是認證用的域名。建議將realm設爲null以使用默認的設置。[3] NTLM只是認證了一個鏈接而不是一請求,因此每當一個新的鏈接創建就要進行一次認證,且在認證的過程當中保持鏈接是很是重要的。 所以,NTLM不能同時用於代理認證和服務器認證,也不能用於HTTP1.0鏈接或服務器不支持持久鏈接(keep-alives)的狀況。關於NTLM認證機制更詳細的研究,可參考http://davenport.sourceforge.net/ntlm.html 。 加密

3.4選擇認證一些服務器支持多種認證方案。假設一次只能使用一種認證方案,HttpClient必須選擇使用哪一種。spa

HttpClient選擇是基於NTLM, Digest, Basic順序的。在具體狀況下,能夠更改該順序。.net

可經過參數'http.auth.scheme-priority'來實現,該參數值應該被存放在一個String類型的List中。選擇優先級是按插入順序肯定的。
HttpClient client = new HttpClient();

List authPrefs = new ArrayList(2);

authPrefs.add(AuthPolicy.DIGEST);

authPrefs.add(AuthPolicy.BASIC);// This will exclude the NTLM

authentication schemeclient.getParams().setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY, authPrefs);

3.5定製認證方案HttpClient自己支持basic, digest, and NTLM這三種認證方案。同時,它也提供了加載額外定製的認證方案的功能(經過AuthScheme接口實現)。

須要使用定製的認證方案,必須實現下面的步驟:

[1]實現AuthScheme接口。

[2]經過AuthPolicy.registerAuthScheme() 註冊定製的AuthScheme。

[3]將定製的AuthScheme加入到AuthPolicy.AUTH_SCHEME_PRIORITY中。

相關文章
相關標籤/搜索