Python高級應用(3)—— 為你的項目添加驗證碼


驗證碼簡介

驗證碼的作用:

驗證碼在現在來說,是很常見的東西,可以一定程度的保護網站,比如防止網絡爬蟲惡意爬取網站數據啊,減少低級的攻擊啊什么的。但是高級點的騷操作還是不太好防范,所以現在的驗證碼平台也在升級強化,為了把人和機器嚴格分開。但是這東西,永遠都是看哪一方技術高低的,誰的技術高級,誰就能干倒另一方了。詳細的就不說了,總而言之,驗證碼可以說是目前所有的面向用戶的平台都會用到的,所以這項技能必須得會啊。

 

 

使用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),

]
urls
# 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")
views
<!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">密&nbsp;&nbsp;&nbsp;&nbsp;碼:</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>
login.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")
views

 

第四版,點擊驗證碼自動刷新

按照電腦常識,應該得有這個功能,點擊圖片刷新啊,因為看不清啊,就點擊刷新,但是如果刷新整個頁面的話,表單上已經填好的內容就沒了,所以,對了,搞前端的朋友估計更熟一點,用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>
login.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', ], }, }, ]
View Code

 

把根目錄的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>密&nbsp;&nbsp;&nbsp;&nbsp;碼:</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">密&nbsp;&nbsp;&nbsp;&nbsp;碼:</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">密&nbsp;&nbsp;&nbsp;&nbsp;碼:</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>
index.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()), ]
url
<!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">密&nbsp;&nbsp;&nbsp;&nbsp;碼:</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>
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)
views

 

 

 然后還有一些其他的驗證方式,有手機頁面的,有先點提交再驗證驗證碼的,反正就自己去玩了,我覺得還是挺簡單的 

 

關於極驗怎么接入到前后端分離的djangorestframework項目的教程,請移步:前后端分離djangorestframework—— 接入第三方的驗證碼平台

 

總結:

  • 1.自定義驗證碼不是不可用,可以自己練練手,做圖形識別練習也是可以的
  • 2.第三方驗證平台,其實用多了第三方的平台,基本就是那幾個步驟,下載sdk,融到自己代碼中,根據文檔配置參數,調整下就行了
  • 3.使用極驗加入自定義的項目時,一定要遷移數據庫,再運行項目,因為會用到django自帶的django_session表做session會話保存

 

  

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM