Flask學習之旅–用 Python + Flask 製作一個簡單的驗證碼系統

  • 2019 年 10 月 3 日
  • 筆記

一、寫在前面

  現在無論大大小小的網站,基本上都會使用驗證碼,登錄的時候要驗證,下載的時候要驗證,而使用的驗證碼也從那些簡簡單單的字元圖形驗證碼“進化”成了需要進行圖文識別的驗證碼、需要拖動滑塊的滑動驗證碼、甚至還有手機驗證碼。當你與之打交道的時候,有沒有考慮過其背後的原理呢?當然了,對於那些複雜的驗證碼我們想要弄得一清二楚還是很難的,但是可以挑軟柿子捏嘛–字元圖形驗證碼,就這樣,我決定用 Python + Flask 製作出一個簡單的驗證碼系統來,話不多說,擼起袖子加油干!

  

 

二、基本思路

  一個簡單的驗證碼系統,要實現的目標包括能夠不斷刷新驗證碼和對用戶輸入的內容進行驗證,若驗證成功則進行後續操作,若失敗則給出提示資訊並要求重新輸入。

  但是沒有大量驗證碼圖片怎麼辦呢?正所謂“自己動手,豐衣足食”,Python 所具有的豐富的第三方庫使得產生大量驗證碼圖片這一需求變得甚是簡單了,這裡主要使用的模組是 pillow。

  有了驗證碼圖片之後,要做的就是將其顯示在前端頁面上,並且要能夠更新驗證碼,這利用 Flask 可以很方便地實現。然後就是輸入驗證碼和對輸入的內容進行驗證了,這裡我是用 JS 實現驗證的。

 

三、具體步驟

1.生成驗證碼圖片

  前面已經提過這一步主要使用的模組是 pillow,沒有安裝的話可以使用 pip install pillow 進行安裝。

  PIL:Python Image Library,是 Python 處理圖片的標準庫,不過 PIL 僅支援到 Python2.7,之後有人在其基礎上創建了兼容的版本,名字就叫做 pillow。

  新建一個 Flask 項目:CaptchaTest,然後創建一個 generate.py。要生成一個驗證碼圖片,首先得創建一張圖片,可以用 pillow 模組中的 Image.new() 實現。然後需要生成驗證碼文本並將其寫入到前面生成的圖片上,除此之外,我們還可以加入一些干擾元素增加識別的難度。下面是幾張生成的驗證碼圖片:

  

  最終得到的生成驗證碼圖片的程式碼如下:

 1 from random import randint   2 from PIL import Image, ImageDraw, ImageFont   3   4   5 def get_random_color():   6     # 隨機顏色RGB   7     return randint(120, 200), randint(120, 200), randint(120, 200)   8   9  10 def get_random_code():  11     # 隨機字元  12     codes = [[chr(i) for i in range(48, 58)], [chr(i) for i in range(65, 91)], [chr(i) for i in range(97, 123)]]  13     codes = codes[randint(0, 2)]  14     return codes[randint(0, len(codes)-1)]  15  16  17 def generate_captcha(width=140, height=60, length=4):  18     # 生成驗證碼  19     img = Image.new("RGB", (width, height), (250, 250, 250))  20     draw = ImageDraw.Draw(img)  21     font = ImageFont.truetype("static/font/font.ttf", size=36)  22     # 驗證碼文本  23     text = ""  24     for i in range(length):  25         c = get_random_code()  26         text += c  27  28         rand_len = randint(-5, 5)  29         draw.text((width * 0.2 * (i+1) + rand_len, height * 0.2 + rand_len), c, font=font, fill=get_random_color())  30     # 加入干擾線  31     for i in range(3):  32         x1 = randint(0, width)  33         y1 = randint(0, height)  34         x2 = randint(0, width)  35         y2 = randint(0, height)  36         draw.line((x1, y1, x2, y2), fill=get_random_color())  37     # 加入干擾點  38     for i in range(16):  39         draw.point((randint(0, width), randint(0, height)), fill=get_random_color())  40     # 保存圖片  41     img.save("static/captcha/" + text + ".jpg")  42     return text + ".jpg"  43  44  45 if __name__ == "__main__":  46     for i in range(1000):  47         generate_captcha()

2.顯示驗證碼圖片

  在進行完上一步之後,我們已經得到了1000張驗證碼圖片,都保存在 static 下的 captcha 文件夾下。那麼現在的問題就是如何將驗證碼圖片顯示在頁面上,要解決這個問題,首先要定義一個路由,用於隨機選取驗證碼圖片並返迴路徑。

  在 Flask 中 route() 裝飾器把一個函數綁定到 URL 上,不僅能配置靜態 URL,而且能配置動態 URL,不過這裡使用靜態 URL 就行了。定義該路由的程式碼如下:

1 @app.route('/get_captcha', methods=['GET'])  2 def get_captcha():  3     img_list = os.listdir("static/captcha")  4     img = img_list[random.randint(0, 1000)]  5     return os.path.join("static/captcha", img)

  其中 os.listdir() 用於列舉文件夾下的內容,os.path.join() 用於返回圖片路徑。

3.刷新驗證碼圖片

  刷新驗證碼圖片的功能可以通過使用 Ajax 來實現,主要過程是先向後端發送請求,請求成功之後會得到一個驗證碼圖片路徑, 然後再設置圖片的 src 屬性,達到刷新驗證碼的目的。在 Ajax 中的 URL 可以直接寫靜態 URL,還能使用 url_for 來反向解析獲取對應的 URL,使用方法如下:

 1 <script>   2     function Change() {   3         $.ajax({   4             url: '{{ url_for('get_captcha') }}',   5             async: true,   6             type: "GET",   7             success: function (data) {   8                 document.getElementById("captcha").src = data;   9             }  10         })  11     }  12 </script>

4.驗證碼內容驗證

  在輸入驗證碼內容後,需要對輸入的內容進行驗證。因為前面生成驗證碼圖片的時候直接用的圖片內容來命名的,所以這裡就可以用 JavaScript 來獲取圖片名稱,再將輸入框中的內容獲取到,把兩者進行比對,這一步還可以做一個忽略大小寫,至於具體程式碼就不放了。

 

四、運行截圖

  首先是一張運行頁面的截圖,點擊“看不清楚,換一張”可以刷新驗證碼,點擊“確認”可以驗證輸入的內容是否正確:

  

   當輸入的內容正確的時候,給出一個驗證成功的提示:

  

   到這裡為止,一個簡單的驗證碼系統就做出來了,當然還有很多可以去完善的地方,比如使用更複雜的驗證碼,對驗證次數進行限制等等。

 

   完整程式碼已上傳到 GitHub