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
- 首先 XMLHttpRequest 出於安全考慮是不支援跨域的, 這一點postman已經向瀏覽器聲明瞭需要跨域的許可權
- 其次,部分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了。