如何使用HttpClient認證機制


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

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);

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得到的軟件支持多,但還是有廣泛的使用。

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

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必須選擇使用哪種。

HttpClient選擇是基於NTLM, Digest, Basic順序的。在具體情況下,可以更改該順序。

可通過參數'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中。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM