HTTP之X-Requested-With分析和思考

  本文主要是針對自己在實際的協議分析過程中遇到的X-Requested-With頭域進行了分析,主要分析了該頭域爲什麼會出現,以及在什麼情況下出現。好像是同一個問題,但是細究還是有所不同。

  最近在報文抓包的時候遇到了X-Requested-With頭域,該頭域在RFC2616中並未提及,以X打頭的頭域作爲非HTTP標準協議,一般是某種技術的出現而產生或者某個組織指定的,像我遇到的X-Requested-With頭域就是用來判斷一個請求是傳統的HTTP請求,還是Ajax請求。也就是說Ajax的請求一般都會帶上X-Requested-With頭域。有一個比較有趣的X頭域就是x-up-calling-line-id其值是用戶終端手機號碼,還有就是諾基亞的wap網關頭域x-nokia-msisdn其值也是表示手機號碼,是未加密的文本。更多的X頭域我是參考瞭如下網址http://www.yeeyan.org/articles/view/37503/37323。

  因爲X-Requested-With頭域作爲一個特徵被協議識別廣泛的應用,因此就花了一點時間研究一下這個非標準HTTP/1.1也就是RFC2616中並沒有提到的頭域。Http2.0沒有拜讀過,但是大概掃了一下目錄,裏面並沒有加入對X-Requested-With的支持(主要原因個人猜測是不是在制定草稿的時候Ajax應用還不是很廣泛,Http2.0正式版好像剛發佈吧),不過這也都沒有關係,TCP/IP的四層模型也和標準的七層模型不一致,這並不妨礙TCP應用的很廣泛。對於X-Requested-With背後的Ajax技術也是一樣。Ajax技術在不加載整個網頁的情況下,更新部分的網頁,是一種異步的JavaScript和XML,應用非常廣泛,不然我們協議分析也不能夠老是遇到這個頭域啊。剛纔提的HTTP2.0參考http://yuedu.baidu.com/ebook/478d1a62376baf1ffc4fad99,這個是由百度FEX團隊人員花費近半年時間翻譯完成,應該比較專業了,不像我在看Http1.1的時候,中文翻譯的真不如直接看英文原版的。

  前面提到X-Requested-With頭域是用來判斷一個請求是傳統的HTTP請求,還是Ajax請求,用JSP寫web服務器端的代碼如下:

  if(request.getHeader("X-Requested-With") != null         

        &&request.getHeader("X-Requested-With").equalsIgnoreCase("XMLHttpRequest")){ 

        out.print("該請求是 AJAX 異步HTTP請求。"); 

  }else{  

        out.print("該請求是傳統的 同步HTTP請求。"); 

        }

  但是該代碼還是有問題的,因爲在實際的抓包過程之中X-Requested-With的值是多種多樣的,默認可能會設置X-Requested-With爲XMLHttpRequest(設置成XMLHttpRequest的原因是XMLHttpRequest類是Ajax的基礎,Ajax使用該對象來發送數據),但並不總是這樣,因爲前臺的請求可以是如下的代碼:HttpRequest對象.setRequestHeader("X-Requested-With","任意字符串")。

  任意字符串可以被被設置爲XMLHttpRequest。但是在實際的抓包分析過程中X-Requested-With的值在很多的情況下跟各個應用是相關的,比如我分析的包中存在X-Requested-With: cld.navi.mainframe這樣的頭域,我們通過這個頭域可以表明有一定概率確定該報文爲該類應用。

  另一個有趣的現象是該頭域出現的時機問題,按照前面提到的凡是使用了Ajax技術的都有可能出現這樣一個頭域。但是抓包的過程中X-Requested-With這個頭域並不總是會出現,這可能是在前臺沒有設置的問題。我們通常抓的包中存在了許多流(由5元組來確定的),這裏面主要是指針對同一個應用有很多流,因爲應用的端口老是出現變化(原因還有待於進一步探索背後的祕密)。而目前我發現X-Requested-With這個屬性頭域出現往往是(以APP爲例)在APP訪問外鏈的流量的時候,會產生該頭域,外鏈的流量嵌入在屬於該APP的頁面中。比如我所分析的地圖類軟件,往往其中會連接到某個賣車網站。賣車網站的流量並不應該歸屬於該地圖的流量,雖然理論上是這麼回事,但是有的局方是要求把該流量歸屬到地圖中,那麼其識別往往用到該字段。爲什麼會產生這樣一個現象,不可能是人家軟件爲了讓我們識別做的好事吧。以前曾想過我們現有的識別引擎非常複雜,如果每款應用之中加入類似與ID這樣一個字段,這樣識別就非常簡單了。其實這個X-Requested-With有點類似於ID的雛形,包括Host也是這樣一個概念。但是加入這樣一個ID字段會導致什麼樣的問題是值得我們思考的問題,不然的話,各大組織爲什麼不積極推動這樣一個字段的制定呢?

  前面我們提到的web服務器端的代碼表明我們可以在服務器端寫如下代碼request.getHeader("X-Requested-With").equalsIgnoreCase("cld.navi.mainframe")),客戶端添加HttpRequest對象.setRequestHeader("X-Requested-With","cld.navi.mainframe "),也就是說一方知道另一方的請求數據具體來自哪裏,這往往可以用於在A,B兩方合作的時候,A能夠知道B具體給自己帶來了多少的異步訪問量,或者說A會針對來自B的請求優先處理等等。但是這時候會出現一個問題,如果我自己開發了一個APP,我在我的前端設置了HttpRequest對象.setRequestHeader("X-Requested-With","cld.navi.mainframe "),那不是給人家搗亂了嗎。其實也不必擔心,頭域中不是還存在Referer屬性域,再不濟我使用POST方法傳一個key就好了。對於我們協議分析來說,如果單獨使用X-Requested-With頭域,風險還是很大的。比如X-Requested-With:cld.navi.mainframe定位爲某個應用,但是如果該流之中的Host爲百度文庫的Host,那麼如果百度文庫協議之中使用了該Host強特徵,就會出現誤識別的情況,這時候優先級高的將會被優先識別。因此針對具體的業務,首先要定位這條流屬於那一個業務比較合理,然後再決定是否添加該特徵是很重要的。

  至於把X-Requested-With設置爲XMLHttpRequest,那就沒有告訴對方該請求來自哪裏,或者乾脆就不設置該頭域字段,這貌似說得通哈。但是如果不設置的話,對於我們識別來說,那麼難度就會增加,可能後面會用到設置事件等技術,這是後話。關於X-Requested-With頭域出現的時機這個問題目前還處於自己對報文分析的推測階段,也請大神多多吐槽。

  這些僅僅是我實際分析協議過程中思考總結的內容,可能還會有諸多的不足和錯誤的地方,也請大家指正。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章