java httpclient進行digest鑒權遇到的問題


最近做接觸java開發,在使用java的httpclient時遇到了兩個問題,這兩個問題都是關於digest鑒權的問題,需求主要是通過http對接服務器,服務器是嵌入式設備,開啟了digest鑒權。

第一個問題:在使用postMethod 方法發送大文件時,httpclient報出來IO異常,抓包后發現,第一次發送的請求沒有攜帶鑒權信息,服務器(嵌入式設備)接收完首部發現沒有鑒權信息時直接返回了401並直接關閉了連接。這時由於文件比較大,還沒有全部發送出去,而socket連接被服務器關閉了,httpclient內部將http主體寫入socket時拋出了IO異常。簡單百度了一下,沒有搜索到解決方案,而項目不能等,看了一下源碼流程,暫時規避該問題。規避方式如下:

 1 PostMethod postMethod = new PostMethod(url){
 2             Integer flag = 0;
 3             protected boolean writeRequestBody(HttpState state, HttpConnection conn) throws IOException, HttpException {
 4                 if (flag == 0){
 5                     flag = 1;
 6                     return true;
 7                 }else {
 8                     return super.writeRequestBody(state, conn);
 9                 }
10             }
11         };

重寫了PostMethod類的writeRequestBody方法,在第一次調用該方法時,不寫消息體直接返回。由於第一次發送是不攜帶鑒權信息,服務器必然返回401,因此不寫消息體也沒有影響,第二次攜帶鑒權信息時,調用原來的writeRequestBody方法正常寫入消息體就能正常發送數據了。該臨時規避的方式存在一個問題,請求必須是需要鑒權的,否則該請求發送的主體回為空。

第二個問題:由於嵌入式設備實現問題,httpclient每一個請求都需要登錄一次,服務器(設備)都需要生成一個nonce。當httpclient較為頻繁的調用時,服務端允許存在的nonce達到上限,所有請求直接失敗,過一段時間后恢復正常。之后一直間歇性失敗。一開始嘗試使用同一個httpclient發起所有請求,抓包發現這樣還是每個請求都需要重新發起一次鑒權,僅僅使用了http長連接。網上也沒有收到解決方案。看了下源碼找了一個規避方案,規避方案如下:

final AuthState tmpState = new AuthState();
GetMethod Get = new GetMethod(url){
            public AuthState getHostAuthState(){
                return tmpState;
            }
        };

對httpclient進行封裝,在內部定義一個AuthState 類的實例。並重寫GetMethod類的getHostAuthState方法(其他http請求方法同理),重寫的getHostAuthState返回我們自己定義的AuthState 實例。該實例是用來保存鑒權信息的,當服務端返回401時,會攜帶鑒權需要的信息,如:nonce等,httpclient會解析這些信息並保存在AuthState 中,而這個實例本身是 定義在GetMethod類中的,這樣每個請求一開始都無法獲取上一個請求發起時服務端返回回來的鑒權信息,需要重新服務器重新返回鑒權信息。重寫后的XXXMethod獲取的都是同一個AuthState ,在服務器返回的nonce失效前都可以重復使用,不用不停生成新的nonce。

 

以上兩個問題是使用httpclient發起請求時遇到的問題,在網上沒有收到解決方案,因此記錄一下。java也是開始接觸,也許有其他更好的方式,如果有知道的,請告知一下,謝謝!

另外:問題是在工作中遇到的,由於公司政策的問題,不方便放源碼,只能記錄一下大概思路。

 


免責聲明!

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



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