驗證碼簡介
驗證碼的作用:
驗證碼在現在來說,是很常見的東西,可以一定程度的保護網站,比如防止網絡爬蟲惡意爬取網站數據啊,減少低級的攻擊啊什么的。但是高級點的騷操作還是不太好防范,所以現在的驗證碼平台也在升級強化,為了把人和機器嚴格分開。但是這東西,永遠都是看哪一方技術高低的,誰的技術高級,誰就能干倒另一方了。詳細的就不說了,總而言之,驗證碼可以說是目前所有的面向用戶的平台都會用到的,所以這項技能必須得會啊。
使用Python庫自定義驗證碼
要自己定義驗證碼,就得使用pillow庫,先用pip install pillow 安裝,安裝步驟就略過了
這里就直接給一個demo作為講解,創建一個簡單的django項目,項目名為LoginAuth,app名為generic
第一版,圖片存在磁盤里
url:
get_validCode_Img就是獲取驗證碼的路由
view:
- get_random_color是獲取隨機的三個顏色,因為三原色(三基色,具體哪個不深究,這不是重點)就可以組成所有的顏色,所以這里用random隨機生成不同的顏色
- get_valid_code_img視圖函數就是利用了pillow庫的功能
- Image是pillow的畫板,ImageDraw是是畫筆,ImageFont是字體,我這用的字體是windows電腦自帶的arial.ttf,你們也可以去網上下載那種很炫酷的字體放進去,注意路徑就行
- ImageDraw.draw.text就是寫字的用法,第一個參數是寫字的位置,第二個參數就是要寫的具體數據
- chr()函數可以將整形數字轉為字母,但必須與ASCII碼對應,不然容易有問題
- 最后的Image.save就是將剛才的畫好的數據保存到一個文件,這個文件當然得是二進制的格式了,然后再讀出來返回,這里估計有朋友會想,我塔碼的不可以直接把剛才的數據返回嗎?不存到圖片直接返回,你可以試試,你找找Image對象在沒保存之前有沒有可以讀取它的數據的方法 /滑稽
其他的有關pillow庫的具體方法就不多說了,感興趣自己去研究了
html模板文件,login.html,我引入了bootstrap的cdn,然后用了bt的css樣式,在驗證碼部分,直接用src請求訪問,這里有點jsonp的意思
啟動項目,打開/login頁面,端口綁定的8002
OJBK
第二版,存在內存IO里
但是,就剛才圖片那里,如果以后項目上線,供多個賬戶使用,不同時段都有很多的賬戶訪問,登錄平台,那么這個圖片我們知道直接就保存在當前目錄里:
這樣的話就很占空間了,所以我們可以利用IO模塊,將這個圖片直接存在內存里,不存在磁盤上
只修改視圖函數的部分,其他沒有做任何改動:
全部代碼:

from django.contrib import admin from django.urls import re_path, path from generic.views import login, get_valid_code_img urlpatterns = [ path('admin/', admin.site.urls), path('login/', login), path('get_validCode_img/', get_valid_code_img), ]

# coding:utf-8 from django.shortcuts import render from django.http import HttpResponse, JsonResponse from django.contrib import auth from PIL import Image, ImageDraw, ImageFont import random import io def get_random_color(): return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) def get_valid_code_img(request): # 方式1 : img = Image.new("RGB", (270, 40), color=get_random_color()) draw = ImageDraw.Draw(img) arial_font = ImageFont.truetype("arial.ttf", size=26) valid_code_str = "" for i in range(5): random_num = str(random.randint(0, 9)) random_low_alpha = chr(random.randint(95, 122)) random_upper_alpha = chr(random.randint(65, 90)) random_char = random.choice([random_num, random_low_alpha, random_upper_alpha]) draw.text((i * 50 + 20, 5), random_char, get_random_color(), font=arial_font) # 保存驗證碼字符串 valid_code_str += random_char # with open("validCode.png", "wb") as f: # img.save(f, "png") # with open("validCode.png", "rb") as f: # data = f.read() f = io.BytesIO() img.save(f, "png") data = f.getvalue() return HttpResponse(data) def login(request): if request.method == "POST": response = {"user": None, "msg": None} user = request.POST.get("user") pwd = request.POST.get("pwd") valid_code = request.POST.get("valid_code") valid_code_str = request.session.get("valid_code_str") if valid_code.upper() == valid_code_str.upper(): user = auth.authenticate(username=user, password=pwd) if user: auth.login(request, user) # request.user== 當前登錄對象 response["user"] = user.username else: response["msg"] = "用戶名或者密碼錯誤!" else: response["msg"] = "驗證碼錯誤!" return JsonResponse(response) return render(request, "login.html")

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>登錄</title> <script src="http://code.jquery.com/jquery-1.12.3.min.js"></script> <!-- 最新版本的 Bootstrap 核心 CSS 文件 --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <!-- 最新的 Bootstrap 核心 JavaScript 文件 --> <script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script> </head> <body> <div class="container"> <h3 class="btn btn-danger">用戶登錄</h3> <div class="row"> <div class="col-md-4 col-lg-offset-4"> <form action="" method="post"> {% csrf_token %} <div class="form-group"> <label for="user">用戶名:</label> <input type="text" id="user" class="form-control" name="user"> </div> <div class="form-group"> <label for="pwd">密 碼:</label> <input type="password" id="pwd" class="form-control" name="pwd"> </div> <div class="form-group"> <label for="valid_code">驗證碼</label> <div class="row"> <div class="col-md-6"> <input type="text" class="form-control" id="valid_code"> </div> <div class="col-md-6"> <img width="170" height="30" id="valid_code_img" src="/get_validCode_img/" alt=""> </div> </div> </div> <p class="error"></p> <input type="button" class="btn btn-primary login_btn btn-block" value="立即登錄"> </form> </div> </div> </div> </body> </html>
第三版,驗證碼添加噪點噪線
因為如上的圖片是很容易被機器識別的,所以為了增加識別難度,可以添加噪點噪線
其中把驗證碼存入request.sessoin是為了做比對驗證的,這里就不多說了
啟動項目:
好的,這就是添加了噪點噪線
代碼(其他沒變,只改了生成驗證碼的函數):

# coding:utf-8 from django.shortcuts import render from django.http import HttpResponse, JsonResponse from django.contrib import auth from PIL import Image, ImageDraw, ImageFont import random import io def get_random_color(): return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) def get_valid_code_img(request): # 方式1 : img = Image.new("RGB", (270, 40), color=get_random_color()) draw = ImageDraw.Draw(img) arial_font = ImageFont.truetype("arial.ttf", size=26) valid_code_str = "" for i in range(5): random_num = str(random.randint(0, 9)) random_low_alpha = chr(random.randint(95, 122)) random_upper_alpha = chr(random.randint(65, 90)) random_char = random.choice([random_num, random_low_alpha, random_upper_alpha]) draw.text((i * 30 + 30, 0), random_char, get_random_color(), font=arial_font) # 保存驗證碼字符串 valid_code_str += random_char width = 170 height = 30 # 噪線 for i in range(3): # 三條線,也可以更多 x1 = random.randint(0, width) x2 = random.randint(0, width) y1 = random.randint(0, height) y2 = random.randint(0, height) draw.line((x1, y1, x2, y2), fill=get_random_color()) # 噪點 for i in range(50): # 50個噪點,也可以更多 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 + 4, y + 4), 0, 90, fill=get_random_color()) # 登錄驗證相關 request.session["valid_code_str"] = valid_code_str request.session['count'] = 0 # with open("validCode.png", "wb") as f: # img.save(f, "png") # with open("validCode.png", "rb") as f: # data = f.read() f = io.BytesIO() img.save(f, "png") data = f.getvalue() return HttpResponse(data) def login(request): if request.method == "POST": response = {"user": None, "msg": None} user = request.POST.get("user") pwd = request.POST.get("pwd") valid_code = request.POST.get("valid_code") valid_code_str = request.session.get("valid_code_str") if valid_code.upper() == valid_code_str.upper(): user = auth.authenticate(username=user, password=pwd) if user: auth.login(request, user) # request.user== 當前登錄對象 response["user"] = user.username else: response["msg"] = "用戶名或者密碼錯誤!" else: response["msg"] = "驗證碼錯誤!" return JsonResponse(response) return render(request, "login.html")
第四版,點擊驗證碼自動刷新
按照電腦常識,應該得有這個功能,點擊圖片刷新啊,因為看不清啊,就點擊刷新,但是如果刷新整個頁面的話,表單上已經填好的內容就沒了,所以,對了,搞前端的朋友估計更熟一點,用ajax異步請求,只讓圖片部分刷新就行了,方法是可行的,不過有個更好用的方法,為地址后面加一個【?】即可,對了我下面那個ajax請求的是對用戶名和密碼的ajax請求驗證,並不是對驗證碼的
啟動項目:
一直點,它就一直做jsonp請求並刷新,是不是很方便?
相關代碼(跟上面的代碼比較只有html文件改了,其他沒有變的)

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>登錄</title> <script src="http://code.jquery.com/jquery-1.12.3.min.js"></script> <!-- 最新版本的 Bootstrap 核心 CSS 文件 --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <!-- 最新的 Bootstrap 核心 JavaScript 文件 --> <script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script> </head> <body> <div class="container"> <h3 class="btn btn-danger">用戶登錄</h3> <div class="row"> <div class="col-md-4 col-lg-offset-4"> <form action="" method="post"> {% csrf_token %} <div class="form-group"> <label for="user">用戶名</label> <input type="text" id="user" class="form-control" name="user"> </div> <div class="form-group"> <label for="pwd">密碼</label> <input type="password" id="pwd" class="form-control" name="pwd"> </div> <div class="form-group"> <label for="valid_code">驗證碼</label> <div class="row"> <div class="col-md-6"> <input type="text" class="form-control" id="valid_code"> </div> <div class="col-md-6"> <img width="170" height="30" id="valid_code_img" src="/get_validCode_img/" alt=""> </div> </div> </div> <p class="error"></p> <input type="button" class="btn btn-primary login_btn btn-block" value="立即登錄"> </form> </div> </div> </div> </body> <script type="text/javascript"> $(function(){ $('#valid_code_img').click(function(){ $(this)[0].src += '?' }); {#定義一個ajax請求函數#} function userlogin(){ $.ajax({ url:'', type:'POST', data:{ csrfmiddlewaretoken:$('input[name="csrfmiddlewaretoken"]').val(), user:$('#user').val(), pwd:$('#pwd').val(), codeimg:$('#valid_code').val() }, success:function(data){ if(data.user){ location.href ='/index'; }else{ $('#user').val(''); $('#pwd').val(''); $('.error').text(data.msg).css({ 'color':'red', 'margin-left':'10px' }); setTimeout(function () { $('.error').text(''); },3000) } }, }) } {# 監聽登錄按鈕#} $('.login_btn').click(function(){ userlogin(); }); {# 監聽回車按鍵#} $('body').keydown(function(e){ if(event.keyCode == 13){ userlogin(); } }); }) </script> </body> </html>
自定義驗證碼就完了,你可以考慮在實際項目上線時就用自己定義的這個驗證碼服務,但是我想你應該猜到了,這種的還是不太好,畢竟還是太簡單的驗證操作了(當然沒說不可以用啊,根據自己的平台選擇),現在利用Python做一個深度學習,三兩下就把你這個驗證碼搞定了,所以呢,還想更安全一點,可以使用第三方的驗證碼平台
使用第三方的驗證碼
如下:
常用的驗證碼平台:
騰訊雲和阿里雲分別都有自己的驗證碼,然后就極驗,還有一些其他的我叫不上名的,本教程按極驗的官方文檔gt3作為案例解析 極驗官網
就這博客園的驗證碼好像也是用的極驗,小米官網貌似也用的極驗,我感覺極驗挺好的,所以采用他們的
前提:
環境:后端:Python3的django2
安裝:
1.使用官方教程安裝:
按照極驗的 官方文檔 來,下載sdk包,解壓得:
然后進入解壓的目錄,使用python setup.py install安裝,但是會報如下錯誤:
這是一個坑,官方文檔並沒有做注明,打開setup文件:
看到了吧,Python中根本沒有utf8的編碼,改成【utf-8】即可,保存,重新使用命令安裝:
最后提示安裝完成:
由極驗的官方文檔可知,極驗支持Python的django ,flask,Tornado 三個框架,這里我使用django簡單創建一個示例看是否安裝成功,項目名為gtdemo,app名為gtapp:
按照官方文檔,直接導入用使用,但會報錯,根本找不到包:
但是查看安裝的包確實存在的:
這又是一個坑,此時需要這樣,找到剛才那個解壓目錄下的這了:
將geetest.py文件復制到項目的目錄里,我這創建了一個utils文件夾,放到此文件夾里:
同樣的,記得改這里的編碼:
然后再使用導包命令並運行測試:
沒報錯,這才是完事兒了。
還有就是此時用的geetest文件並不是安裝包根目錄的geetest.py文件,這兩個文件雖然名字一樣,但是是完全不同的,根目錄那個文件內容,它只是輔助的安裝文件
此時我們用到的文件,全部代碼就不展示了,看我勾選的部分,就是我們准備導入的模塊:
所以這個文件才是對的
2.使用pip安裝
由於我電腦裝了Python2和3,3剛才是按官方文檔手動安裝的且已經安裝了,所以這里在Python2下用pip安裝:
注:這里安裝之后能不能直接用要自己去試驗,我的是可以導包,但是具體開發沒有測試,有時間的朋友可以自己測試,我感覺這樣安裝更方便,但有沒有問題就不好說了
還要一個坑,如果運行django跑不起來,提示要social_django:
需要安裝這個模塊 social-auth-app-django 才行
這時會安裝一大堆東西,安裝完就可以用了
注冊賬號
用別人的東西肯定要有一個賬號才行,去極驗官網注冊一個賬號,極驗的賬號分了個人和公司,按情況來定,我這注冊的是個人號,然后完成后面的操作
注冊完賬號之后登陸極驗的后台,這些步驟不用展示了,電腦常識就不啰嗦了,登陸之后選行為驗證:
新增一個驗證:
根據情況來填:
部署:
部署服務端
點這里的指引也可以去官方文檔
現在點左邊的管理設置,拿到id和key,這是創建驗證時自動生成的,這兩個參數在代碼部署會用到
現在終於開始代碼編寫了,后續步驟按照官方文檔沒什么大的坑了,可以跟着官方文檔走了,當然你也可以接着看我的教程,主要就根據實際情況來規划代碼怎么編寫了
部署客戶端:
官方文檔里有相關的參數配置:點我查看
具體就自己研究了
下面給一個實例
示例使用
創建一個django項目
當然在下載geetest時,解壓目錄里其實有模板,可以直接用那個,當然你也可以自定義,我這就直接用極驗官方給的模板
但是注意,官方給的是django1的,如果你的django是1那么直接可以用,如果你的跟我一樣是django2,那必須做如下修改才行,我給的都是修改過后的,修改之前直接看給的模板:
url:
view:
配置文件里其他不用改,添加這個TEMPLATES參數:
代碼:

TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')] , 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ]
把根目錄的static文件改成templates:
啟動項目:
訪問/home:
點擊提交又報錯了:
這里又有一個坑,沒用過django1和Django2的朋友可能在這里就迷糊了,這里說的意思是WSGIRequest對象沒有session屬性,我打開wsgi發現根本沒啥可改的,經查,還是配置文件的問題,把MIDDLEWARE_CLASS(這是django1的寫法)改成MIDDLEWARE即可
然后下面這個中間件也要注釋掉,不然一樣報錯:
調整后測試
改好重啟,訪問/home頁面,點擊提交,終於有了我們想要的驗證了:
極驗提供的驗證碼,下面還有兩個:
測試了幾次之后沒有問題
這幾個組件就是極驗官方提供的模板,index.html文件里的:
index.html全部代碼:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>gt-python-django-demo</title>
<style> body { margin: 50px 0; text-align: center; } .inp { border: 1px solid gray; padding: 0 10px; width: 200px; height: 30px; font-size: 18px; } .btn { border: 1px solid gray; width: 100px; height: 30px; font-size: 18px; cursor: pointer; } #embed-captcha { width: 300px; margin: 0 auto; } .show { display: block; } .hide { display: none; } #notice { color: red; } /* 以下遮罩層為demo.用戶可自行設計實現 */ #mask { display: none; position: fixed; text-align: center; left: 0; top: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.5); overflow: auto; } /* 可自行設計實現captcha的位置大小 */ .popup-mobile { position: relative; } #popup-captcha-mobile { position: fixed; display: none; left: 50%; top: 50%; transform: translate(-50%, -50%); -webkit-transform: translate(-50%, -50%); z-index: 9999; } </style>
</head>
<body>
<h1>極驗驗證SDKDemo</h1>
<br><br>
<hr>
<br><br>
<!-- 為使用方便,直接使用jquery.js庫,如您代碼中不需要,可以去掉 -->
<script src="http://code.jquery.com/jquery-1.12.3.min.js"></script>
<!-- 引入封裝了failback的接口--initGeetest -->
<script src="http://static.geetest.com/static/tools/gt.js"></script>
<!-- 若是https,使用以下接口 -->
<!-- <script src="https://code.jquery.com/jquery-1.12.3.min.js"></script> -->
<!-- <script src="https://static.geetest.com/static/tools/gt.js"></script> -->
<div class="popup">
<h2>彈出式Demo,使用ajax形式提交二次驗證碼所需的驗證結果值</h2>
<br>
<p>
<labe>用戶名:</labe>
<input id="username1" class="inp" type="text" value="極驗驗證">
</p>
<br>
<p>
<label>密 碼:</label>
<input id="password1" class="inp" type="password" value="123456">
</p>
<br>
<input class="btn" id="popup-submit" type="submit" value="提交">
<div id="popup-captcha"></div>
</div>
<script>
var handlerPopup = function (captchaObj) { // 成功的回調
captchaObj.onSuccess(function () { var validate = captchaObj.getValidate(); $.ajax({ url: "/pc-geetest/ajax_validate", // 進行二次驗證
type: "post", dataType: "json", data: { username: $('#username1').val(), password: $('#password1').val(), geetest_challenge: validate.geetest_challenge, geetest_validate: validate.geetest_validate, geetest_seccode: validate.geetest_seccode }, success: function (data) { if (data && (data.status === "success")) { $(document.body).html('<h1>登錄成功</h1>'); } else { $(document.body).html('<h1>登錄失敗</h1>'); } } }); }); $("#popup-submit").click(function () { captchaObj.show(); }); // 將驗證碼加到id為captcha的元素里
captchaObj.appendTo("#popup-captcha"); // 更多接口參考:http://www.geetest.com/install/sections/idx-client-sdk.html
}; // 驗證開始需要向網站主后台獲取id,challenge,success(是否啟用failback)
$.ajax({ url: "/pc-geetest/register?t=" + (new Date()).getTime(), // 加隨機數防止緩存
type: "get", dataType: "json", success: function (data) { // 使用initGeetest接口
// 參數1:配置參數
// 參數2:回調,回調的第一個參數驗證碼對象,之后可以使用它做appendTo之類的事件
initGeetest({ gt: data.gt, challenge: data.challenge, product: "popup", // 產品形式,包括:float,embed,popup。注意只對PC版驗證碼有效
offline: !data.success // 表示用戶后台檢測極驗服務器是否宕機,一般不需要關注
// 更多配置參數請參見:http://www.geetest.com/install/sections/idx-client-sdk.html#config
}, handlerPopup); } }); </script>
<br><br>
<hr>
<br><br>
<form class="popup" action="/pc-geetest/validate" method="post">
<h2>嵌入式Demo,使用表單形式提交二次驗證所需的驗證結果值</h2>
<br>
<p>
<label for="username2">用戶名:</label>
<input class="inp" id="username2" type="text" value="極驗驗證">
</p>
<br>
<p>
<label for="password2">密 碼:</label>
<input class="inp" id="password2" type="password" value="123456">
</p>
<div id="embed-captcha"></div>
<p id="wait" class="show">正在加載驗證碼......</p>
<p id="notice" class="hide">請先拖動驗證碼到相應位置</p>
<br>
<input class="btn" id="embed-submit" type="submit" value="提交">
</form>
<script>
var handlerEmbed = function (captchaObj) { $("#embed-submit").click(function (e) { var validate = captchaObj.getValidate(); if (!validate) { $("#notice")[0].className = "show"; setTimeout(function () { $("#notice")[0].className = "hide"; }, 2000); e.preventDefault(); } }); // 將驗證碼加到id為captcha的元素里,同時會有三個input的值:geetest_challenge, geetest_validate, geetest_seccode
captchaObj.appendTo("#embed-captcha"); captchaObj.onReady(function () { $("#wait")[0].className = "hide"; }); // 更多接口參考:http://www.geetest.com/install/sections/idx-client-sdk.html
}; $.ajax({ // 獲取id,challenge,success(是否啟用failback)
url: "/pc-geetest/register?t=" + (new Date()).getTime(), // 加隨機數防止緩存
type: "get", dataType: "json", success: function (data) { // 使用initGeetest接口
// 參數1:配置參數
// 參數2:回調,回調的第一個參數驗證碼對象,之后可以使用它做appendTo之類的事件
initGeetest({ gt: data.gt, challenge: data.challenge, product: "embed", // 產品形式,包括:float,embed,popup。注意只對PC版驗證碼有效
offline: !data.success // 表示用戶后台檢測極驗服務器是否宕機,一般不需要關注
// 更多配置參數請參見:http://www.geetest.com/install/sections/idx-client-sdk.html#config
}, handlerEmbed); } }); </script>
<br><br>
<hr>
<br><br>
<div class="popup-mobile">
<h2>移動端手動實現彈出式Demo</h2>
<br>
<p>
<labe for="username3">用戶名:</labe>
<input id="username3" class="inp" type="text" value="極驗驗證">
</p>
<br>
<p>
<label for="password3">密 碼:</label>
<input id="password3" class="inp" type="password" value="123456">
</p>
<br>
<input class="btn" id="popup-submit-mobile" type="submit" value="提交">
<div id="mask"></div>
<div id="popup-captcha-mobile"></div>
</div>
<script> $("#mask").click(function () { $("#mask, #popup-captcha-mobile").hide(); }); $("#popup-submit-mobile").click(function () { $("#mask, #popup-captcha-mobile").show(); }); var handlerPopupMobile = function (captchaObj) { // 將驗證碼加到id為captcha的元素里
captchaObj.appendTo("#popup-captcha-mobile"); //拖動驗證成功后兩秒(可自行設置時間)自動發生跳轉等行為
captchaObj.onSuccess(function () { var validate = captchaObj.getValidate(); $.ajax({ url: "/mobile-geetest/ajax_validate", // 進行二次驗證
type: "post", dataType: "json", data: { // 二次驗證所需的三個值
username: $('#username3').val(), password: $('#password3').val(), geetest_challenge: validate.geetest_challenge, geetest_validate: validate.geetest_validate, geetest_seccode: validate.geetest_seccode }, success: function (data) { if (data && (data.status === "success")) { $(document.body).html('<h1>登錄成功</h1>'); } else { $(document.body).html('<h1>登錄失敗</h1>'); } } }); }); // 更多接口參考:http://www.geetest.com/install/sections/idx-client-sdk.html
}; $.ajax({ // 獲取id,challenge,success(是否啟用failback)
url: "/mobile-geetest/register?t=" + (new Date()).getTime(), // 加隨機數防止緩存
type: "get", dataType: "json", success: function (data) { // 使用initGeetest接口
// 參數1:配置參數
// 參數2:回調,回調的第一個參數驗證碼對象,之后可以使用它做appendTo之類的事件
initGeetest({ gt: data.gt, challenge: data.challenge, offline: !data.success // 表示用戶后台檢測極驗服務器是否宕機,一般不需要關注
// 更多配置參數請參見:http://www.geetest.com/install/sections/idx-client-sdk.html#config
}, handlerPopupMobile); } }); </script>
</body>
</html>
官方文檔里還有很多驗證組件:點我查看
感興趣自己去研究了,實際開發的話,就根據自己的情況稍微改改就行了
實際案例:
本次選用的驗證組件時最常用的先滑動認證,再提交表單的:
做一個簡單的登錄驗證平台,但是不完全用極驗官方的,業務代碼自己做,畢竟這東西要拿到我們實際開發中,不可能只用用官方給的幾個小demo就完事兒了,開發環境是Python的django2:
創建一個django項目:
然后配置:
url,注意關於兩個極驗的url都指向的是一個視圖類:
view:
html:
標簽元素部分:
js部分:
注意,這里還有一個坑,瑪德,在這耗了有點久,因為geetest調用了request.session,所以,使用django默認的數據庫表django_session,必須要先遷移數據庫,再啟動項目訪問,不然報如下錯:
django.db.utils.OperationalError: no such table: django_session
最后啟動訪問:
說明一下,這里訪問時,去geetest官網請求需要一段時間,所以剛開始打開有正在加載驗證的字樣,等幾秒鍾就有了
點擊驗證:
驗證成功的,后面的結果就不展示了
詳細的代碼,其實都沒改多少,就只是把自己的業務邏輯加上去了,其他的都是直接用極驗官方的

from django.contrib import admin from django.urls import re_path, path from generic.views import AuthView from generic.views import GtView urlpatterns = [ path('admin/', admin.site.urls), path('auth/', AuthView.as_view()), re_path(r'^pc-geetest/register', GtView.as_view()), re_path(r'^pc-geetest/validate$', GtView.as_view()), ]

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>gt-python-django-demo</title>
<style> body { margin: 50px 0; text-align: center; } .inp { border: 1px solid gray; padding: 0 10px; width: 200px; height: 30px; font-size: 18px; } .btn { border: 1px solid gray; width: 100px; height: 30px; font-size: 18px; cursor: pointer; } #embed-captcha {
width: 300px; margin: 0 auto; } .show { display: block; } .hide { display: none; } #notice {
color: red; } </style>
</head>
<body>
<h1>請登錄</h1>
<br><br>
<!-- 為使用方便,直接使用jquery.js庫,如您代碼中不需要,可以去掉 -->
<script src="http://code.jquery.com/jquery-1.12.3.min.js"></script>
<!-- 引入封裝了failback的接口--initGeetest -->
<script src="http://static.geetest.com/static/tools/gt.js"></script>
<form class="popup" action="/pc-geetest/validate" method="post">
<p>
<label for="username2">用戶名:</label>
<input class="inp" id="username2" type="text" value="極驗驗證">
</p>
<br>
<p>
<label for="password2">密 碼:</label>
<input class="inp" id="password2" type="password" value="123456">
</p>
<div id="embed-captcha"></div>
<p id="wait" class="show">正在加載驗證碼......</p>
<p id="notice" class="hide">請先拖動驗證碼到相應位置</p>
<br>
<input class="btn" id="embed-submit" type="submit" value="提交">
</form>
<script> var handlerEmbed = function (captchaObj) { $("#embed-submit").click(function (e) { var validate = captchaObj.getValidate(); if (!validate) { $("#notice")[0].className = "show"; setTimeout(function () { $("#notice")[0].className = "hide"; }, 2000); e.preventDefault(); } }); // 將驗證碼加到id為captcha的元素里,同時會有三個input的值:geetest_challenge, geetest_validate, geetest_seccode captchaObj.appendTo("#embed-captcha"); captchaObj.onReady(function () { $("#wait")[0].className = "hide"; }); // 更多接口參考:http://www.geetest.com/install/sections/idx-client-sdk.html }; $.ajax({ // 獲取id,challenge,success(是否啟用failback) url: "/pc-geetest/register?t=" + (new Date()).getTime(), // 加隨機數防止緩存 type: "get", dataType: "json", success: function (data) { // 使用initGeetest接口 // 參數1:配置參數 // 參數2:回調,回調的第一個參數驗證碼對象,之后可以使用它做appendTo之類的事件 initGeetest({ gt: data.gt, challenge: data.challenge, product: "embed", // 產品形式,包括:float,embed,popup。注意只對PC版驗證碼有效 offline: !data.success // 表示用戶后台檢測極驗服務器是否宕機,一般不需要關注 // 更多配置參數請參見:http://www.geetest.com/install/sections/idx-client-sdk.html#config
}, handlerEmbed); } }); </script>
</body>
</html>

# coding:utf-8 from django.shortcuts import render from django.http import HttpResponse from django.views import View from utils.geetest import GeetestLib # 這個id和key是極驗給的demo里的,我建議還是去官網注冊一個自己的,免費注冊的 pc_geetest_id = "b46d1900d0a894591916ea94ea91bd2c" pc_geetest_key = "36fc3fe98530eea08dfc6ce76e3d24c4" class AuthView(View): def get(self, request): return render(request, "index.html") class GtView(View): def get(self, request): user_id = 'test' gt = GeetestLib(pc_geetest_id, pc_geetest_key) status = gt.pre_process(user_id) request.session[gt.GT_STATUS_SESSION_KEY] = status request.session["user_id"] = user_id response_str = gt.get_response_str() return HttpResponse(response_str) def post(self, request): gt = GeetestLib(pc_geetest_id, pc_geetest_key) challenge = request.POST.get(gt.FN_CHALLENGE, '') validate = request.POST.get(gt.FN_VALIDATE, '') seccode = request.POST.get(gt.FN_SECCODE, '') status = request.session[gt.GT_STATUS_SESSION_KEY] user_id = request.session["user_id"] if status: result = gt.success_validate(challenge, validate, seccode, user_id) else: result = gt.failback_validate(challenge, validate, seccode) result = "<html><body><h1>登錄成功</h1></body></html>" if result else "<html><body><h1>登錄失敗</h1></body></html>" return HttpResponse(result)
然后還有一些其他的驗證方式,有手機頁面的,有先點提交再驗證驗證碼的,反正就自己去玩了,我覺得還是挺簡單的
關於極驗怎么接入到前后端分離的djangorestframework項目的教程,請移步:前后端分離djangorestframework—— 接入第三方的驗證碼平台
總結:
- 1.自定義驗證碼不是不可用,可以自己練練手,做圖形識別練習也是可以的
- 2.第三方驗證平台,其實用多了第三方的平台,基本就是那幾個步驟,下載sdk,融到自己代碼中,根據文檔配置參數,調整下就行了
- 3.使用極驗加入自定義的項目時,一定要遷移數據庫,再運行項目,因為會用到django自帶的django_session表做session會話保存