第三方驗證碼插件的使用
官方文檔:http://django-simple-captcha.readthedocs.io/en/latest/usage.html#installation
github:https://github.com/mbi/django-simple-captcha
django-simple-captcha 一個很簡單的django驗證組件,實現原理是數據庫中生成key和隨機字符,然後將key與sn存入數據庫,用戶提交時根據key去數據庫中查詢比對是否正確,沒有使用常用的cookies session, 也挺簡單,每個驗證碼都有過期時間,程序會自動清除過期的驗證碼
django 版本:1.9.1
安裝
pip install django-simple-captcha==0.4.6
在setting 中配置
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'captcha',
]
url中的配置
加入url(r'^captcha/', include('captcha.urls')),
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^captcha/', include('captcha.urls')),
]
數據庫的遷移
makemigrations
migrate
app下自定義froms.py文件,創建一個註冊form
from django import forms
from captcha.fields import CaptchaField
class RegisterForm(forms.Form):
email = forms.EmailField(required=True)
password = forms.CharField(required=True, min_length=5)
captcha = CaptchaField(error_messages={"invalid": u"驗證碼錯誤"})
視圖函數中處理
class RegisterView(View):
"""註冊視圖"""
def get(self, request):
register_form = Registerform() # 獲取表單對象 然後返回前端
return render(request, 'register.html', {'register_form': register_form})
def post(self, request):
print(request.POST) #打印下提交的數據
register_form = Registerform(request.POST)
if register_form.is_valid():
pass
else:
print(register_form.errors)
前端處理 在form表單中引用這個變量
{{ register_form.captcha }}
在用js實現點擊驗證碼 就能進行切換
支持大小寫
在前端生成的內容 :
<label>驗 證 碼</label>
<img src="/captcha/image/d8826580b3125692f6e2f55eef81d906cc0b5d8e/" alt="captcha" class="captcha" /> <input id="id_captcha_0" name="captcha_0" type="hidden" value="d8826580b3125692f6e2f55eef81d906cc0b5d8e" /> <input autocomplete="off" id="id_captcha_1" name="captcha_1" type="text" />
下面是自己實現的驗證碼
依賴pillow庫
生成驗證碼代碼:
# coding=utf-8
import random
import string
from PIL import Image, ImageDraw, ImageFilter, ImageFont
import io # python3 中是io pytho2 中是 stringIo
# image 負責處理圖片
# ImageDraw 負責處理畫筆
# ImageFont 負責處理畫筆
# ImageFilter 負責處理 過濾鏡
def create_check():
# 1 創建畫布
img = Image.new("RGB", (150, 50), (255, 255, 255))
"""
第一個參數: 代表要採用RGB的顏色模式
第二個參數:代表圖片的大小
第三個參數:具體的圖片的顏色
"""
# 2 創建畫筆
draw = ImageDraw.Draw(img)
# 3 繪製線條和點
# 繪製線
for i in range(random.randint(1, 10)):
# for i in range(5):
draw.line(
# 在繪製線條的時候 是需要兩個點確定一條直線的 每個點靠x y 兩個值來確定位置的
[
(random.randint(1, 150), random.randint(1, 150)), # 這個是一個 x 和 y 確定的座標的位置
# 第二個x 和 要確定的 座標的位置 兩個座標 確定了一條直線
(random.randint(1, 150), random.randint(1, 150))
],
fill=(0, 0, 0)
)
# 開始繪製點
for j in range(1000):
draw.point(
[
random.randint(1, 150),
random.randint(1, 150)
],
fill=(0, 0, 0)
)
# 4 繪製文字
str_temp = string.ascii_letters # 生成大小寫字母
digtial_temp = string.digits # 生成數字 0-9
font_list = list(str_temp + digtial_temp) # 組合成一個list列表
c_chars = "".join(random.sample(font_list, 5)) # 從指定的列表中隨機的返回固定的長度的字符
# 5 繪製字體
font = ImageFont.truetype("simsun", 32) # 這個字體是怎麼設置的????? 需要使用什麼樣的 字體
draw.text((5, 5), c_chars, font=font, fill="green")
"""
第一個參數:代表文字的位置 距離上和左的距離
第二個參數:代表文字的內容
第三個參數:代表文字的字體和大小
第四個參數:代表字體的顏色
"""
# 5 定義扭曲的參數
params = [1 - float(random.randint(1, 2)) / 100,
0,
0,
0,
1 - float(random.randint(1, 2)) / 100,
float(random.randint(1, 2)) / 500,
0.001, # 總體的比列
float(random.randint(1, 1)) / 500,
]
# 6 使用濾鏡 添加濾鏡
img = img.transform((150, 50), Image.PERSPECTIVE, params)
# 扭曲的範圍 扭曲的樣式 扭曲的參數
# 進行扭曲
img = img.filter(ImageFilter.EDGE_ENHANCE_MORE)
# 展示畫布
# img.save("demo.jpg") # 保存文件 返回圖片的內容 然後把內容保存在內存中 這裏就不再在保存在本地了
# img.show() # 這個是展示生成的圖片的
return img, c_chars # 給調用者返回這個img 也可以不用返回 直接生成在內存中
在視圖函數中調用驗證碼
# 導入工具包中的生成圖片的方法
from utils import check_code
import io # 可以把圖片保存咋內存中
# 調用生成驗證碼的方法 並把驗證碼存入內存中 返回給前端
def tupian(request):
"""獲取驗證碼圖片"""
img, c_chars = check_code.create_check()
# 上面調用了生成圖片的函數 返回了生成圖片的對象 和生成圖片上面的文字
stream = io.BytesIO() # 返回一個內存的字節流對象
img.save(stream, 'png') # 把圖片保存在內存中 然後 直接從內存中讀取返回
# 把生成圖片的字母保存在session
request.session['c_chars'] = c_chars
return HttpResponse(stream.getvalue()) # 直接去內存中 取出對象 然後進行返回
# 驗證提交上來的驗證碼
def yanzhengma(request):
"""返回驗證碼錶單"""
if request.method == 'GET':
return render(request, "驗證碼.html")
elif request.method == 'POST':
yanzhengma = request.POST.get("yanzhengma")
# 獲取session 中保存的驗證碼的信息 然後和用戶提交上來的進行對比
c_chars = request.session['c_chars']
# 把session中的 和獲取到的字符串全部 變成 小寫 來進行對比
yanzhengma = yanzhengma.lower()
c_chars = c_chars.lower()
if yanzhengma == c_chars:
return HttpResponse("登陸成功".encode())
else:
return HttpResponse("登陸失敗".encode())
前端處理
<body>
<h3>驗證碼錶單</h3>
<div class="container">
<form action="/login/yanzhengma/" method="POST">
<input type="text" name="yanzhengma" id="yanzhengma">
<input type="file" name="file" id="file">
<input type="submit" id="submit">
</form>
</div>
<div id="see">
<h5>驗證碼</h5>
{% comment %}在這裏請求圖片的時候就會返回這個視圖函數讀取的內容{% endcomment %}
<img src="/login/tupian/" alt="" onclick="change_yanzhengma(this)">
</div>
<script>
//點擊圖片換驗證碼
function change_yanzhengma(ths) {
//點擊圖片進行切換 給img加上一個點擊事件 然後
// 然後去重新給這個src 來賦值 獲取原來的再加上個?
//動態的去改變URL的地址
ths.src = ths.src + "?";
}
</script>
</body>