最近和眾屌絲一樣,在12306上面刷著春節回家的票。與她大戰無數個回合之後,終於搶到了一張回家的高鐵票,不斷感慨最近人品還不錯。當前,在使用12306的過程中,充滿很多的心酸,念叨了鐵道部的親人很多次(罪過),其中最讓人糾結的一項即是:驗證碼。
12306採用驗證碼, 無疑是一種很不錯的措施,可以在一定程度上阻止了黃牛們的瘋狂行為,不過也給正常使用驗證碼的童鞋帶了個很頭痛的問題,在選座提交訂單的關鍵時候,竟然驗證碼拉取不下來又或者驗證過程非常耗時。鑑於自己也是無數碼農中的有這職業病的一員,為此也來談談關於驗證碼的優化方案。
驗證碼通常一張靜態的,但是12306使用的卻是一張動態的(gif格式),動態的驗證碼大大的提高了破解的難度,但無疑也具備比較高的生成成本。我們首先來看一下通常情況下的驗證碼校驗流程:
1)瀏覽器向驗證碼伺服器發起獲取驗證碼的請求;
2)驗證碼伺服器返回驗證碼檔案和檔案對應的id編號(id編號一般下發到瀏覽器的cookie中);
3)瀏覽器提交使用者輸入的驗證碼和檔案id編號;
4)web伺服器校驗使用者輸入的驗證碼與中展示的驗證碼是否一致,根據校驗結果來向使用者展示不同的頁面;
下面我們來看一下系統的整體架構圖:
主要處理流程為:
1、獲取驗證碼
1)從配置中心中獲取當前可用的頻率控制、驗證碼庫、待驗證庫可用的服務位址列表
2)頻率控制,主要控制當前請求是否屬於惡意攻擊;
3)驗證碼庫,獲取可用的驗證碼資訊,即獲取乙個可用的驗證碼檔案位址;
4)將獲取到的驗證碼資訊寫入到待驗證庫中,方便後續進行校驗驗證碼;
2、校驗驗證碼
1)根據從前端獲取到的編號(獲取驗證碼時,下發的對應編號),來從待驗證庫中獲取驗證資訊;
2)將驗證結果傳送到校驗統計模組;
在設計過程中需要考慮的點:
1)惡意重新整理
來自某個ip頻繁的請求驗證碼,大體上就可以判定驗證碼正在被刷中,需要採取措施進行一定的頻率限制,降低繼續被刷的請求量,這裡我們可以採用比較簡單限制來個某個ip請求次數,當然也可以根據業務特性,新增業務對應的頻率控制邏輯;
2)驗證碼有效期
驗證碼可以生成一條key—value的資料存放到memcache中(即待驗證庫),value為:驗證碼檔案id、驗證碼code、生成時間,每個請求驗證碼的請求,均在快取中插入一條記錄,每傳送乙個驗證請求,即將快取中的這條記錄刪除失效。
3)檔案與編號
兩者之間不可以建立一一對應的關係,否則,壞人只需要儲存編號,下次就可以重複提交對應的驗證碼;但是可以建立一對多的關係,也就是一張對應多個編號,但是一編號只能唯一對應;
4)驗證碼生成
驗證碼檔案的生成相比而言是比較慢的操作,所以需要採用離線計算成功的方案,避免瀏覽器獲取驗證碼檔案耗時比較久,影響使用者的體驗;這裡存放乙個問題,什麼時機啟動驗證碼生成的流程,有以下幾種策略:
a)每天定時生成更新,策略簡單實現;
b)定時檢測驗證碼可用量,來生成一批新的驗證碼檔案;
總之,驗證碼檔案的生成必須是離線進行的,同時在此時需要為檔案生成乙個或者多個編號;服務部署的個數,完全取決於驗證碼的消耗量;
5)驗證碼庫
驗證碼庫,應該採用那種資料結構?mysql還是其他的資料結構。在這裡,可以嘗試採用redis的list結構來當作訊息佇列來使用或者其他的可用的訊息佇列。需要獲取驗證碼時,從訊息佇列中pop出乙個值即可。每個記錄中至少需要儲存的字段為:編號、位址、驗證碼等資訊。訊息佇列中的記錄 < 50%時,可以出發驗證碼生成邏輯來定時插入新的驗證碼。面對更併發的驗證碼請求量,可以在集群中多部署幾套redis訊息佇列以及驗證碼生成系統來應對;
6)編號的生成
驗證碼檔案需要支援在多台機器上面部署多個服務,同時也要支援在單機上面部署多個服務,這裡就需要解決如何來生成唯一驗證碼編號的問題。可以通過根據機器ip和服務編號來解決這個問題,每台機器上面的服務均存在乙個服務編號(保證服務編號在單機上是唯一的),計算公式可以為:id = md5(ip+服務編號+時間戳+自動序列號);
從12306談起驗證碼的架構
最近和眾屌絲一樣,在12306上面刷著春節回家的票。與她大戰無數個回合之後,終於搶到了一張回家的高鐵票,不斷感慨最近人品還不錯。當前,在使用12306的過程中,充滿很多的心酸,念叨了鐵道部的親人很多次 罪過 其中最讓人糾結的一項即是 驗證碼。12306採用驗證碼,無疑是一種很不錯的措施,可以在一定程...
12306驗證碼 驗證碼的架構
最近和眾屌絲一樣,在12306上面刷著春節回家的票。與她大戰無數個回合之後,終於搶到了一張回家的高鐵票,不斷感慨最近人品還不錯。當前,在使用12306的過程中,充滿很多的心酸,念叨了鐵道部的親人很多次 罪過 其中最讓人糾結的一項即是 驗證碼。12306採用驗證碼,無疑是一種很不錯的措施,可以在一定程...
python 爬取12306驗證碼
import ssl import urllib2 i 1import time while 1 不加的話,無法訪問12306 time.sleep 1 有時需要加延時,以防被封。i i 1 f.write data f.close 以下就是爬取的 的截圖 12306的驗證碼經常讓人眼花繚亂,眼睛仔...