為了防止機器人頻繁登錄網站或者破壞分子惡意登錄,很多用戶登錄和注冊系統都提供了圖形驗證碼功能。
驗證碼(CAPTCHA)是“Completely Automated Public Turing test to tell Computers and Humans Apart”(全自動區分計算機和人類的圖靈測試)的縮寫,是一種區分用戶是計算機還是人的公共全自動程序。可以防止惡意破解密碼、刷票、論壇灌水,有效防止某個黑客對某一個特定注冊用戶用特定程序暴力破解方式進行不斷的登陸嘗試。
圖形驗證碼的歷史比較悠久,到現在已經有點英雄末路的味道了。因為機器學習、圖像識別的存在,機器人已經可以比較正確的識別圖像內的字符了。但不管怎么說,作為一種防御手段,至少還是可以抵擋一些低級入門的攻擊手段,抬高了攻擊者的門檻。
在Django中實現圖片驗證碼功能非常簡單,有現成的第三方庫可以使用,我們不必自己開發(也要能開發得出來,囧)。這個庫叫做django-simple-captcha
。
一、安裝captcha
在Pycharm的terminal中,使用pip安裝第三方庫:
執行命令:pip install django-simple-captcha -i http://pypi.mirrors.ustc.edu.cn/simple/ --trusted-host pypi.mirrors.ustc.edu.cn
(venv) D:\work\2019\for_test\mysite>pip install django-simple-captcha Collecting django-simple-captcha Downloading https://files.pythonhosted.org/packages/86/d4/5baf10bfc9eb7844872c256898a405e81f22f7213e008ec90875689f913d/django-simple-captcha-0 .5.11.zip (234kB) 100% |████████████████████████████████| 235kB 596kB/s Collecting six>=1.2.0 (from django-simple-captcha) Downloading https://files.pythonhosted.org/packages/73/fb/00a976f728d0d1fecfe898238ce23f502a721c0ac0ecfedb80e0d88c64e9/six-1.12.0-py2.py3-none -any.whl Requirement already satisfied: Django>=1.8 in d:\work\2019\for_test\mysite\venv\lib\site-packages (from django-simple-captcha) (2.2) Collecting Pillow!=5.1.0,>=2.2.2 (from django-simple-captcha) Downloading https://files.pythonhosted.org/packages/40/f2/a424d4d5dd6aa8c26636969decbb3da1c01286d344e71429b1d648bccb64/Pillow-6.0.0-cp37-cp37m -win_amd64.whl (2.0MB) 100% |████████████████████████████████| 2.0MB 2.2MB/s Collecting django-ranged-response==0.2.0 (from django-simple-captcha) Downloading https://files.pythonhosted.org/packages/70/e3/9372fcdca8e9c3205e7979528ccd1a14354a9a24d38efff11c1846ff8bf1/django-ranged-response- 0.2.0.tar.gz Requirement already satisfied: sqlparse in d:\work\2019\for_test\mysite\venv\lib\site-packages (from Django>=1.8->django-simple-captcha) (0.3.0) Requirement already satisfied: pytz in d:\work\2019\for_test\mysite\venv\lib\site-packages (from Django>=1.8->django-simple-captcha) (2018.9) Installing collected packages: six, Pillow, django-ranged-response, django-simple-captcha Running setup.py install for django-ranged-response ... done Running setup.py install for django-simple-captcha ... done Successfully installed Pillow-6.0.0 django-ranged-response-0.2.0 django-simple-captcha-0.5.11 six-1.12.0
pip自動幫我們安裝了相關的依賴庫six
、olefile
和Pillow
,其中的Pillow是大名鼎鼎的繪圖模塊。
二、注冊captcha
在settings中,將‘captcha’注冊到app列表里:
# Application definition INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'login', 'captcha', ]
captcha需要在數據庫中建立自己的數據表,所以需要執行migrate命令生成數據表:
(venv) D:\work\2019\for_test\mysite>python manage.py migrate Operations to perform: Apply all migrations: admin, auth, captcha, contenttypes, login, sessions Running migrations: Applying captcha.0001_initial... OK
三、添加url路由
在根目錄下的urls.py文件中增加captcha對應的url:
from django.contrib import admin from django.urls import path from django.urls import include from login import views urlpatterns = [ path('admin/', admin.site.urls), path('index/', views.index), path('login/', views.login), path('register/', views.register), path('logout/', views.logout), path('captcha/', include('captcha.urls')) # 增加這一行 ]
由於使用了二級路由機制,需要在頂部from django.urls import include
。
四、修改forms.py
如果上面都OK了,就可以直接在我們的forms.py文件中添加CaptchaField了。
from django import forms from captcha.fields import CaptchaField class UserForm(forms.Form): username = forms.CharField(label="用戶名", max_length=128, widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': "Username",'autofocus': ''})) password = forms.CharField(label="密碼", max_length=256, widget=forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': "Password"})) captcha = CaptchaField(label='驗證碼')
注意需要提前導入from captcha.fields import CaptchaField
,然后就像寫普通的form字段一樣添加一個captcha字段就可以了!
五、修改login.html
由於我們前面是手動生成的form表單,所以還要修改一下,添加captcha的相關內容,如下所示:
{% load static %}
<!doctype html>
<html lang="en"> <head> <!-- Required meta tags --> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <!-- 上述meta標簽*必須*放在最前面,任何其他內容都*必須*跟隨其后! --> <!-- Bootstrap CSS --> <link href="https://cdn.bootcss.com/twitter-bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet"> <link href="{% static 'login/css/login.css' %}" rel="stylesheet"/> <title>登錄</title> </head> <body> <div class="container"> <div class="col"> <form class="form-login" action="/login/" method="post"> {% if login_form.captcha.errors %} <div class="alert alert-warning">{{ login_form.captcha.errors }}</div> {% elif message %} <div class="alert alert-warning">{{ message }}</div> {% endif %} {% csrf_token %} <h3 class="text-center">歡迎登錄</h3> <div class="form-group"> {{ login_form.username.label_tag }} {{ login_form.username}} </div> <div class="form-group"> {{ login_form.password.label_tag }} {{ login_form.password }} </div> <div class="form-group"> {{ login_form.captcha.label_tag }} {{ login_form.captcha }} </div> <div> <a href="/register/" class="text-success " ><ins>新用戶注冊</ins></a> <button type="submit" class="btn btn-primary float-right">登錄</button> </div> </form> </div> </div> <!-- /container --> <!-- Optional JavaScript --> <!-- jQuery first, then Popper.js, then Bootstrap JS --> {# 以下三者的引用順序是固定的#} <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script> <script src="https://cdn.bootcss.com/popper.js/1.15.0/umd/popper.js"></script> <script src="https://cdn.bootcss.com/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script> </body> </html>
這里在頂部的消息處,在{% if %}
模板代碼中,額外增加了一條{{ login_form.captcha.errors }}
的判斷,用於明確指示用戶的驗證碼不正確。
六、查看效果
重啟服務器,進入登錄頁面,嘗試用用戶名錯誤、密碼不對、驗證碼不對、全對的不同情況,看看我們新增的四位驗證碼的效果如何。
就是這么簡單!我們加入了一個防止機器人或者惡意登錄的圖形驗證碼功能,雖然界面難看了點,但底子是好的,你可以根據需要進行美化。其中驗證圖形碼是否正確的工作都是在后台自動完成的,只需要使用is_valid()
這個forms內置的驗證方法就一起進行了,完全不需要在視圖函數中添加任何的驗證代碼,非常方便快捷!
關於captcha的功能,當然絕不僅限於此,你可以設置六位、八位驗證碼,可以對圖形噪點的生成模式進行定制,這些就留待你自己學習和研究了。