悲劇了,發(fā)現(xiàn)寫完這篇blog沒有配上這個格調(diào)超高的標(biāo)題。
1.0問題背景現(xiàn)在要實現(xiàn)一個帶驗證碼網(wǎng)站的的自動登陸功能。驗證碼識別過程不再這篇文章的討論之中。(之后有篇文章我會詳細(xì)的總結(jié)驗證碼的識別過程)。現(xiàn)在問題來了,怎么拿到你本次請求登陸頁面的驗證碼圖片?2.0方案分析現(xiàn)在有幾種思路:(1)請求登陸頁面,截取驗證碼圖片,類似截屏,seleinum,webbrower的DrawToBitmap()等。(2)還是webbrower,將圖片復(fù)制到剪切板在從剪切板中搞出來
在瀏覽器中我們看到的是這個頁面,我們用fidder抓包發(fā)現(xiàn),我們關(guān)系的請求只有兩次。
所以,我們第三種思路也來了。那我們用webclient或httpwebrequset模擬這兩次請求不就完事了?一次請求登陸頁面,一次請求驗證碼,然后模擬表單提交,多簡單的事!悲劇 就發(fā)生在這:你模擬請求的驗證碼輸入后總是不對,一大堆的人都說你對驗證碼發(fā)了二次請求,你獲得的驗證碼是上一次的!!有的人一想,我靠,是這么回事啊,怪不得不行呢,這方法不行啊。大家仔細(xì)想一想,我怎么對驗證碼發(fā)送二次請求了?老子一共模擬兩次請求,一次請求登陸頁面,一次請求驗證碼,就一次好嗎!所以這種說法是錯誤的,我們從頭來分析:第一次是請求這個登陸頁面,這是請求頭
這是response頭:
我們發(fā)現(xiàn)服務(wù)器向客戶端寫了一個cookie;之后我們討論這個cookie的作用。我們繼續(xù)觀察第二請求,該請求是怎么發(fā)出來的呢?我們現(xiàn)在都應(yīng)該知道了,第一次請求服務(wù)器返回的是這個登陸頁面的html代碼,對吧,瀏覽器拿到這個html代碼后它就要渲染了,就是在瀏覽器給我畫這個漂亮的頁面。當(dāng)它看到這串代碼時 <img width="60" height="25" src='/cas/codeimage/>它就認(rèn)為,這是一個圖片啊,我趕緊去按圖片地址去拿吧,晚了就玩了,這樣,他就發(fā)送了第二個請求。我們來看報文:
發(fā)現(xiàn)了什么,請求報文中竟然帶了cookie。這就要涉及到cookie的工作原理了,cookie是寫在客戶端的,就是一個鍵值對,就是是寫在你瀏覽器對應(yīng)的cookie存放位置,cookie是不能跨瀏覽器的,360瀏覽器的cookie你google瀏覽器是不能玩的。cookie是不能跨域的,就是不能a.com的cookie不能提交到c.com.而且cookie在同一域名下,會自動提交的,這也說明了第二次請求為什么會無緣無故的多了個cookie。cookie的作用path,過期時間等其他參數(shù)這里就不說了。好了,關(guān)鍵的東西我們都發(fā)現(xiàn)了,就是這個cookie搞的。它到底是什么鬼?是干啥的?我們來分析下驗證碼的實現(xiàn)機(jī)制,不是講怎么畫出來的,用戶去請求驗證碼,服務(wù)器生成驗證碼字符,然后把他存在session里,另外又把這個字符串畫到圖片上返回給瀏覽器。有人問session又是什么鬼?session也是一個鍵值對,跟cookie不同的是,session是存在服務(wù)器端的。服務(wù)器端有個session池,里面放的就是一個一個的鍵值對。
我們填完了驗證碼,提交到服務(wù)器,服務(wù)器開始判斷你填的對不對,他怎么判斷的呢?逗比,服務(wù)器不是有session嗎?一比不就得了嘛!怎么比?服務(wù)器的session多了去了,所以只能拿著鍵,去找值,那這個值和你提交過來的值比。那么問題來了,鍵是那來的?你什么時候提交過來的?見鬼了?相信大家都已經(jīng)想到了,這個鍵就是剛才那個cookie的值。這樣大家也就明白了,原來session是通過cookie實現(xiàn)的啊,你以為呢?到這里,我們就找到第二次模擬請求驗證碼過程發(fā)生的問題了。原來是這次請求沒有帶上第一次請給的cookie。你沒帶,說明你提交的鍵是null,服務(wù)器卻是真實有的,當(dāng)然每次請求都錯誤 了。知道錯誤地點(diǎn)了,這問題也就解決了:提交的時候直接帶上第一次的cookie不就結(jié)了。簡單代碼: CookieContainer cookiesContainer = new CookieContainer(); if (response1.Cookies.Count > 0) { cookiesContainer.Add(response1.Cookies); } requst2.CookieContainer =cookieContainer;3.0總結(jié) 這里要說明下,這個cookie是到底什么時候給你寫到客戶端?按道理來講,這個cookie這與你的驗證碼有關(guān),你訪問驗證碼圖片時候,給你寫個才對。但這個實驗網(wǎng)站他訪問登陸頁面就給你寫了,到你訪問驗證碼頁面時候,估計是他先判斷你有沒有寫cookie,沒寫的話給你寫上。所以這cookie在哪還得自己抓包看。另外還有很多隱藏域的值參與驗證,分析的時候也要注意。這還有個問題:服務(wù)器設(shè)定驗證碼session的時候,鍵直接設(shè)置為"VCde",還用從cookie里找干嘛?針對一個用戶來說,這樣是可以的,如果多個用戶同時訪問的話,會發(fā)生什么情況。A剛拿到驗證碼,VCde存的是A的字符。這時候B來登陸,VCde立馬變成B的字符,A興致勃勃的填完了去登陸,驗證碼錯誤!所以,cookie中村的不是vcode的key,他是sessionId,服務(wù)器中是session空間像一個柜子,sessionid就是那個柜子的鑰匙,而柜子里存的才是你網(wǎng)session中存的數(shù)據(jù),當(dāng)然了,驗證碼就存在柜子里。新聞熱點(diǎn)
疑難解答