Django實現隨機驗證碼圖片
現在,每當我們在進行登錄的時候,所有網站幾乎都會讓用戶填寫驗證碼,效果如下圖所示:

本文就為大家講一下用Django如何實現“隨機驗證碼圖片”的。
前端渲染
前端我們需要一個用戶輸入框
以及存放隨機驗證碼圖片的img標簽
<div class="form-group">
<label for="valid_code">驗證碼</label>
<div class="row">
<div class="col-md-6">
<input type="text" id="valid_code" class="form-control">
</div>
<div class="col-md-6">
<img id="valid_code_img" src="/get_validCode_img/" width="260px" height="35px" alt="">
</div>
</div>
</div>
注意這里img的高度是35px,寬度是260px——后面需要注意這個參數。
在img標簽中我們寫了一個src="/get_validCode_img/"
的鏈接,對應到路由中的寫法:
re_path(r'^get_validCode_img/$', views.get_validCode_img),
為了實現解耦
我們的視圖函數中只有調用其他模塊:
def get_validCode_img(request):
##引入獲取隨機驗證碼圖片的模塊
from blog.utils.valid_code import get_valid_code_img
##data獲取
data = get_valid_code_img(request)
##返回
return HttpResponse(data)
可想而知,我們的核心代碼在get_valid_code_img
函數中!
實現隨機驗證碼圖片的完整代碼
這里先給出完整版代碼,下面進行一一詳解
import random
##獲取三個隨機數,用於“顏色的調配”
def get_random_color():
return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
def get_valid_code_img(request):
###基於PIL模塊動態生成狀態碼圖片
##引入相應模塊
from PIL import Image, ImageDraw, ImageFont
from io import BytesIO
##這個大小跟前端的img大小要一致
img = Image.new('RGB', (260, 35), color=get_random_color())
draw = ImageDraw.Draw(img)
##字體對象,字體大小為32
font_obj = ImageFont.truetype('static/font/bmwy.ttf', size=28)
##隨機獲取5位的數字字母的組合
valid_code_str = ''
for i in range(5):
random_num = str(random.randint(0, 9))
random_low_alpha = chr(random.randint(97, 122))
random_upper_alpha = chr(random.randint(65, 90))
random_char = random.choice([random_num, random_upper_alpha, random_low_alpha])
draw.text((i * 50 + 20, 5), random_char, get_random_color(), font=font_obj)
##保存驗證碼字符串
valid_code_str += random_char
##噪點噪線
width = 260
height = 35
##改變range的值可以增加或減少噪點噪線的多少
for i in range(11):
x1 = random.randint(10,width)
x2 = random.randint(10,width)
y1 = random.randint(10,height)
y2 = random.randint(10,height)
draw.line((x1,x2,y1,y2),fill=get_random_color())
for i in range(30):
draw.point([random.randint(0,width),random.randint(0,height)],fill=get_random_color())
x = random.randint(0,width)
y = random.randint(0,height)
draw.arc((x,y,x+14,y+14),0,90,fill=get_random_color())
##將隨機字符串存在session里——再在login()中提取!
##這部分十分重要!要知道三個詳細的流程
request.session['valid_code_str'] = valid_code_str
##保存
f = BytesIO()
img.save(f, 'png')
data = f.getvalue()
return data
具體實現介紹
實現隨機驗證碼圖片的核心模塊時PIL
模塊,我們可以將這個過程分解為如下幾步:一是為我們隨機驗證碼找到一個空間
,而這個空間
的大小正好應該跟我們前端img標簽的大小匹配上,這也就是為什么在前端渲染的時候特意給大家強調了下關注img標簽的大小;第二步就是在我們提供的這個空間上進行背景顏色
以及字體
等設置;第三就是利用程序得到我們需要的“隨機驗證碼”;接着就是將得到的這個“隨機驗證碼”寫入
之前提供好的“空間”中去。最后將這個寫好隨機驗證碼的圖片
存入內存即可。
結合上面的講解與自己的體驗,聰明的你可能會提出下面幾個問題:
一、我們做這個“隨機驗證碼”的目的是“驗證”,得到的圖片並不是最終的目的!在實際中我們需要對用戶的輸入與我們生成的“隨機驗證碼”去匹配,匹配成功后再進行用戶名以及密碼的匹配,如果兩個地方都匹配正確了才顯示登陸成功。
二、生成的隨機驗證碼圖片對人來說很好識別,那么對於機器爬取也是很簡單的一件事情,我們如何做去避免機器爬取生成的圖片里的數據呢?
三、如果由於字體問題用戶“猜”不出來圖中的字母是什么了,有沒有辦法實現“點擊圖片自動刷新驗證碼”呢?
一:
對於第一個問題,我們可以利用session
解決,如前面的代碼所示,將最終的“隨機驗證碼”valid_code_str
保存在session中——request.session['valid_code_str'] = valid_code_str
,而我們在登陸驗證的視圖函數中既可以取到用戶輸入的隨機驗證碼的值,又可以在session中通過 request.session.get('valid_code_str')
方法拿到系統隨機生成的隨機驗證碼,將這兩個值進行比對(如果不想區分大小寫可以將得到的值先upper后再比對)即可。
二:
為了防止程序的“爬取”,我們可以在生成的圖片上加上噪點噪線
,如上面的“噪點噪線”代碼所示,效果如下:

三:
對於點擊刷新圖片驗證碼可以在模板中加一個click事件,修改下src屬性
即可:
//點擊刷新圖片驗證碼
$('#valid_code_img').click(function () {
$(this)[0].src += '?'
});
關於滑動驗證碼
其實現在玩的比較高端的是“滑動驗證碼”,從安全性與復雜度來講都要優於我們的“驗證碼圖片”,關於滑動驗證碼如果大家有興趣的話可以看我在github上傳的項目(基於Django1.8版本的,當然我在django2.0打開也可以用)注意下載里面的名字是django_demo的項目
https://github.com/Wanghongw/django_practice