1. 程式人生 > >postman模擬帶驗證碼登入問題

postman模擬帶驗證碼登入問題

今天研究一個問題,就是用postman模擬網站的帶驗證碼登入。本文把這一過程做個流水賬式記錄。

我最初的設想是這樣:

http是一種無連線無狀態協議,請求相應完畢連線即斷開,由於其無狀態,重複請求的身份認證一般通過session、cookie、url重寫這幾種方式來實現,我們的網站登入採用第三方庫生成圖片驗證碼,同時把驗證碼值存入session中。那麼我可以先用瀏覽器debug登入請求,獲取jsessionid的cookie寫入postman中,然後拼裝登入json進行登入。

實際結果:

登入失敗,驗證碼錯誤。

猜測:是不是跟user-agent有關?

驗證:postman添加了跟chrome一樣的user-agent,依然無效。

猜測:header裡面發現了Connection:keepAlive,這是什麼?是不是連線不關閉了導致外部請求即使有jsessionid也不能訪問這個session?

驗證:keepalive是新版本http中加入的功能,作用是在伺服器和瀏覽器都支援的前提下讓連線不關閉,這樣就避免了頻繁重建連線帶來的效率問題。怎麼才是支援呢?瀏覽器如果支援,會在請求頭新增這個Connection:keepAlive,伺服器如果支援,在接到之後會在響應頭部也新增這一欄位。拿百度來驗證,請求和響應都帶有這個欄位,明顯百度是支援這個功能的,但是我們的伺服器並不支援。所以這不是原因。

猜測:是不是傳的cookie引數無效,兩次訪問屬於不同session?

驗證:確實不一樣。

插播廣告:我想在服務端看看request的header都是些什麼玩意,就在controller裡面加了個httprequest引數,我覺得Spring框架會自動注入,就像httpSession一樣,結果程式掛了。後來發現httpRequest是apache包下的,這個並不能自動注入,得改成HttpServletRequest才可以。

廣告播完了,上面那個不一樣的原因也出來了。就是我在postman裡面寫的headercookie被覆蓋掉了。。其他屬性都正常傳過去,只有cookie,也就是jsessionid被覆蓋了。原因如下:

postman是基於瀏覽器的外掛,發出的請求都是通過呼叫ajax/xmlhttprequest

的方式,必然受到瀏覽器的安全限制:

  1. 首先 XMLHttpRequest 出於安全考慮是不支援跨域的, 這一點postman已經向瀏覽器聲明瞭需要跨域的許可權

  1. 其次,部分header同樣由於安全原因,是無法在瀏覽器中set的,受制於瀏覽器的使用者特性

具體哪些header不能set,要看XMLHttpRequest.js的原始碼實現

var forbiddenRequestHeaders = [
    "accept-charset",
    "accept-encoding",
    "access-control-request-headers",
    "access-control-request-method",
    "connection",
    "content-length",
    "content-transfer-encoding",
    "cookie",
    "cookie2",
    "date",
    "expect",
    "host",
    "keep-alive",
    "origin",
    "referer",
    "te",
    "trailer",
    "transfer-encoding",
    "upgrade",
    "via"   ];

經驗證,以上屬性在postman中設定全部無效。解決方案是開啟postman的攔截器,之後就可以正常新增cookie了。