python-55: 驗證碼的生成機制

前面的嘗試失敗了,爲何呢?程序員

你們能夠看到,咱們使用了兩次urlopen,第一次是打開登錄界面的網址獲取驗證碼的地址,第二次是post數據到指定的網址,咱們雖然獲取到了驗證碼,可是這實際上是一個很虛的事情,爲何這麼說呢?後端

仍是先看前面說的兩個網址,api

  1. http://id.ifeng.com/allsite/login 這是登錄界面的網址,用來顯示輸入界面和接受登錄結果的信息
    瀏覽器

  2. https://id.ifeng.com/api/sitelogin 這是post數據的網址,js腳本,用來向服務器發送數據安全

咱們從登錄界面獲取驗證碼圖片,而後向post數據的網址發送data,那麼,咱們怎麼能肯定這個過程當中驗證碼有沒有改變呢?咱們的程序只進行了獲取驗證碼,輸入驗證嗎,post的操做,可是實際上,這中間具體通過了什麼樣的一個過程咱們並不知道,有可能咱們第二次使用urlopen來post數據的時候,這個驗證碼已經改變了呢?若是真的是這樣,那咱們的代碼獲取的永遠不是最新的驗證碼,這怎麼可能登錄得上呢?服務器

那麼,應該怎麼知道獲取的驗證碼是否是最新的,或者,有沒有什麼方法可以保證post數據裏面的驗證碼跟咱們網頁獲取到的是同一個驗證碼,但同時,我還發現了一個問題
cookie

https://id.ifeng.com/public/authcode 這個是咱們前面使用RE抽取出來的驗證碼的圖片,我以爲這個網址跟我想象中的不同,驗證碼不是每次刷新都不同的嗎?爲何這裏就是是一個網址,甚至連什麼序號之類的都沒有?這不科學session

爲了找出緣由我又從新運行了幾回代碼,發現仍是這個網址,可是點擊進去以後圖片已經變化了,我又把這個網址輸入到瀏覽器的地址欄,不斷的刷新,結果隨着我不斷的刷新,驗證碼的圖片不斷的改變,我很好奇爲何會是這種狀況,因而我請教了一些作網頁設計的朋友post

驗證碼是什麼前面實現那已經說了,那麼如今來講說驗證碼是怎麼生成的
學習

咱們就拿相似於鳳凰網的驗證碼來講吧,在用戶點擊登錄界面的時候,程序會自動生成一個隨機數,並同時將這個隨機數保存到session或者cookies中,生成一個id,以key-values的形式存放,而後經過必定的方法將這些數字或者字母進行處理,好比,扭曲,位置變換等等,最後生成一張圖片並顯示出來,用戶輸入後按key來尋找並對比用戶輸入的數值和隨機數生成的數值是否相同

驗證碼機制是怎麼實現

目前主流的實現技術主要有session和cookie兩種方式,而這兩種方式能夠說技術是同樣的,區別在於將驗證碼字符串存儲在服務器仍是客戶端。
前者工做流程:服務器發送驗證碼圖片到客戶端並在服務器保存驗證碼字符串到session,用戶辨認圖片並提交驗證碼字符串到服務器,服務器將用戶提交的驗證碼字符串與session中保存的字符串進行比較。
後者工做流程:服務器發送驗證碼圖片以及驗證碼字符串(可能會進行加密)到客戶端,客戶端將驗證碼字符串存儲到本地cookie,用戶辨認圖片並提交驗證碼字符串以及cookie中所存儲的字符串到服務器,服務器將用戶提交的兩個字符串(進行解密後)進行比較。
相對而言,存放在服務器的session更爲安全,只不過消耗服務器內存,程序員除了使用模式識別辨認出驗證碼,沒有其餘辦法。而對於使用cookie方式的驗證碼,不增長服務器內存消耗,但咱們能夠經過對傳輸數據進行分析輕易破解驗證碼。

關於cookies和session的更加詳細的信息能夠到這個網站學習:http://blog.csdn.net/fangaoxin/article/details/6952954

通常來講,爲了安全起見,註冊、登錄等這些的驗證碼都是存放在服務器上的,也就是說,大部分是使用session的形式來實現的,若是能找到session-id或者是key,就有辦法獲得驗證碼的數據,可是session不是存放在服務器中嗎?咱們怎麼能獲取獲得呢?

實際上,session是後端的數據,咱們並不知道網站設計者在編寫代碼的時候是怎麼設計的,或者作了什麼限制,總之咱們很難獲取獲得,經過程序不能獲取,甚至瀏覽器也不能獲取,那應該怎麼辦呢?

cookies,咱們知道,瀏覽器向服務器發送請求,服務器響應並返回數據,固然,這些數據中也包含cookies,用戶輸入用戶名和密碼而後登錄網站,若是登錄成功,服務器會將一些信息寫入cookies用於下次打開網頁的時候自動登錄,若是登錄不上,也會將相應的信息寫入cookies,在下次發送請求打開網頁的時候告訴服務器,這個用戶尚未登錄,須要登錄,從這個角度上來講,cookies表明了你的狀態,已經登錄,或者,未登陸

咱們來設想這樣一種狀況,當咱們打開登錄界面的時候,會隨機生成一個驗證碼(好比:1234),並將這個驗證碼的信息生成一個session,好比, {key = session-1, values = 1234},這個session的信息是存放在服務器上面的,它須要保密因此不但願瀏覽器獲取到它,那就不給瀏覽器這些數據,好,如今服務器將不包含有任何session信息的數據返回給瀏覽器,瀏覽器提交驗證碼上的數字來進行登錄,乍一看這整個過程好像沒有什麼錯誤,可是,若是100我的同時進行登錄呢?

100個登錄請求就會生成100個session,若是按照前面的方式,100個瀏覽器同時提交驗證碼,那麼服務器怎麼知道哪一個瀏覽器對應的是哪一個session呢?

因此,最好的辦法是在瀏覽器發出登錄請求的時候,服務器爲瀏覽器生成一個標識,好比,"這是瀏覽器a,它對應的是session-1",固然,這個標識是通過加密的,服務器將這個標識和驗證碼等數據返回給瀏覽器,瀏覽器提交驗證碼的時候要帶上這個標識信息,說,"我是瀏覽器a,對應的是session-1,我提交的驗證碼數據是1234",而後服務器將這些信息進行比對,若是匹配就登錄成功

這也就是cookies的原理,說了這麼多,實際上就是想說明,既然cookies可以攜帶用戶是否已經登錄的信息,那麼,它應該也能夠攜帶驗證碼的信息,雖然不會直接告訴咱們驗證碼是什麼,可是會告訴服務器,"我是瀏覽器a,我剛剛已經請求了一個驗證碼,對應的是session-1" 相似這樣的信息

這也就是咱們前面的代碼爲何不能成功的緣由,咱們沒有告訴服務器咱們發送的驗證碼對應的是哪一個session,這就意味着,咱們須要先獲取cookies,這個cookies裏面包含驗證碼的信息,而後咱們帶着這個cookies去post數據

相關文章
相關標籤/搜索