Django学习笔记(17)——BBS+Blog项目开发(1)验证码功能的实现

  本文主要学习验证码功能的实现,为了项目BBS+Blog项目打下基础。

   为了防止机器人频繁登陆网站或者破坏分子恶意登陆,很多用户登录和注册系统都提供了图形验证码功能。

  验证码(CAPTCHA)是“Completely Automated Public Turing test to tell Computers and Humans Apart”(全自动区分计算机和人类的图灵测试)的缩写,是一种区分用户是计算机还是人的公共全自动程序。可以防止恶意破解密码、刷票、论坛灌水,有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试。

  图形验证码的历史比较悠久,到现在已经有点英雄末路的味道了。因为机器学习、图像识别的存在,机器人已经可以比较正确的识别图像内的字符了。但不管怎么说,作为一种防御手段,至少还是可以抵挡一些低级入门的攻击手段,抬高了攻击者的门槛。

验证码功能实现方法1——完整的验证码实现流程

1, 验证码前端画布页面生成

  那么下面我们将依次生成验证码这种画布,左边框是输入验证码的内容,右边框是设计验证码。

1.1,直接读取图片

  首先,我们需要了解读取图片的方法。

  # 方式一
    with open('kd1.jpg', 'rb') as f:
        data = f.read()

    return HttpResponse(data)

  这样我们知道方法就行,不建议使用,因为这样读取文件,我们需要存很多文件。

1.2,硬盘操作

  首先,我们需要导入库,图像处理库Pillow,如果没有的话,需要先安装pillow库。

  其次,我们创建一个定义随机颜色方法的函数。这函数的意义就是定义画布的背景颜色。

如何定义颜色随机呢?,因为三原色R,G,B的范围都是0-255,我们随机取0-255里面的某一个整数,就得到了随机颜色。代码如下:

#定义随机颜色方法
def get_random_color():
    
    R = random.randrange(255)
    G = random.randrange(255)
    B = random.randrange(255)

    return (R,G,B)

  然后我们设定画布的大小,定义画布的宽和高。然后写一块区域,最后展示在前端页面。

    # 方式二:使用pillow PIL模块
    # pip  install pillow
    from PIL import Image

    # img = Image.new("RGB", (270, 40), color='red')
    img = Image.new("RGB", (270, 40), color=get_random_color())
    with open("validCode.png", "wb") as f:
        img.save(f, 'png')
    with open('validCode.png', 'rb') as f:
        data = f.read()
    return HttpResponse(data)

  

1.3,内存操作

  其实硬盘操作,我们也不建议使用,最好的方法是建议使用内存操作。在上线中大多体验者需要的是速度,如果速度不够快,那就会放弃这个APP,所以我们一般牺牲其空间复杂度,换取时间复杂度。

  那内存操作如何做呢?首先,我们获取一个缓存区,然后将图片保存到缓存区,最后使用一个.getvalue的函数方法将缓存区的内容返回给前端。

  .getvalue  是把缓存区的所有数据读取。

  bytesIO() 是使用io 获取一个缓存区,然后将图片保存到缓存区,最后读取缓存区的数据。

    from PIL import Image, ImageDraw, ImageFont
    from io import BytesIO

    img = Image.new('RGB', (270, 40), color=get_random_color())

    f = BytesIO()
    img.save(f, 'png')
    data = f.getvalue()

  这样的话,一个前端画布就生成了,不仅生成了,我们还解决了速度问题,而且每次刷新,后台都会传出不同颜色的画布。

1.4 效果图

  验证码在前端显示,肯定是左边一格,右边一格。最后设计出来的画布效果是这样的。

  那下面,我们需要给画布里面添加文字了。

2,如何给面板里加文字

  我们需要导入绘图库 ImageDraw, 绘图字体库 ImageFont。还需要下载一个字体样式,直接使用网上的字体样式会比较简单。

2.1,ttf字体下载

  我们可以在网上下载一个ttf字体文件。选择一个自己喜欢的字体形式,下载。我这里下载了三个,这里我使用第三个 Vera.ttf字体。

 2.2 添加文字

   一般情况下,验证码都是由四到八位不等的数字,大小写字母组成。我们这里选择五位,其中每个位里面让随机生成一个大写字母,或者小写字母,或者数字。然后将其保存下来。这就是一个简单的验证码就生成了。

  代码如下:

    # 导入绘图库
    from PIL import Image, ImageDraw, ImageFont
    # 导入IO库
    from io import BytesIO

    img = Image.new('RGB', (270, 40), color=get_random_color())
    draw = ImageDraw.Draw(img)
    vera_font = ImageFont.truetype("static/font/Vera.ttf", size=35)


    #  ttf 字体下载
    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_upper_alpha, random_low_alpha])
        #  x, y  坐标
        draw.text((i*50+20, 5), random_char, get_random_color(), font=vera_font)
        # 保存验证码字符串
        valid_code_str += random_char

  

2.3 效果图

  验证码里面添加五个文字,最后设计出来的添加文字的画布效果是这样的。

3,加上噪点噪线

  其实上面差不多已经完成了验证码的操作,但是这是比较简单的验证码,一般的图片验证码机器就可以识别了。我们需要添加一些难度,比如噪点噪线。

  加噪点噪线也是为了减轻暴力请求,一般的图片验证码机器就可以识别出来,所以我们加点难度,这样可以减轻服务器的压力。

  下面代码中,width和height是前端画布的宽和高,第一个for循环是噪点的加入,第二个for循环是噪线的加入。

    width = 235
    height = 35
    for i in range(100):
        x1 = random.randint(0, width)
        x2 = random.randint(0, width)
        y1 = random.randint(0, height)
        y2 = random.randint(0, height)
        draw.line((x1, x2, y1, y2), fill=get_random_color())

    for i in range(400):
        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())

  x1, y1, x2, y2  则表示需要四个坐标。

 3.1 效果图

    验证码里面添加噪点噪线,因为我还要使用,所以噪点噪线的效果就添加了一点点而已,如果需要复杂,可以添加内容就像,最后设计出来的添加噪点噪线的画布效果是这样的。

4,验证码局部刷新

  为什么要做验证码局部刷新呢?从使用者的角度来说,我们也知道,当前端显示的验证码看不清楚,我们就需要刷新一下,但是不可能不停的提交表单,这样的话,服务器的压力就太大了。所以这时候局部刷新就优势就显现出来了,我们需要局部刷新,很多人就想到了Ajax,没错,这是可以用,但是这里说一种比较简单的局部刷新的方法。

  我们可以看一个例子:

   从上面,我们发现可以使用增加字符的方式,实现局部刷新,那么我们也可以采取这么简单的方法,直接刷新验证码就行了。

  下面展示其代码:

<script src="/static/JS/jquery-3.2.1.js"></script>
<script>
    //刷新验证码
    $("#valid_code_img").click(function () {
        $(this)[0].src += "?"
    })

</script>

  views.py

def get_validCode_image(request):
    def get_random_color():
        return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))

    # 方式四,图片里面什么都没,这里我们需要加上噪点,文字
    from PIL import Image, ImageDraw, ImageFont
    from io import BytesIO

    img = Image.new('RGB', (270, 40), color=get_random_color())
    draw = ImageDraw.Draw(img)
    vera_font = ImageFont.truetype("static/font/Vera.ttf", size=35)

    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_upper_alpha, random_low_alpha])
        #  x, y  坐标
        draw.text((i*50+20, 5), random_char, get_random_color(), font=vera_font)
        # 保存验证码字符串
        valid_code_str += random_char

    width = 235
    height = 35
    for i in range(10):
        x1 = random.randint(0, width)
        x2 = random.randint(0, width)
        y1 = random.randint(0, height)
        y2 = random.randint(0, height)
        draw.line((x1, x2, y1, y2), fill=get_random_color())

    for i in range(40):
        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())

    print('valid_code_str', valid_code_str)

    f = BytesIO()
    img.save(f, 'png')
    data = f.getvalue()

    request.session['valid_code_str'] = valid_code_str

    return HttpResponse(data)

  前端代码:

    // 登录验证
    $(".login_btn").click(function () {
        $.ajax({
            url: "",
            type: 'post',
            data: {
                user: $('#user').val(),
                pwd: $('#pwd').val(),
                valid_code: $("#valid_code").val(),
                csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val(),
            },
            success: function (data) {
                console.log(data);
                if (data.user){
                        if (location.search){
                            location.href = location.search.slice(6)
                        }
                        else {
                            location.href = '/blog/index/'
                        }
                }else {
                    $(".error").text(data.msg).css({'color':'red', 'margin-left':'10px'});
                    //  设置2秒后清空
                    setTimeout(function () {
                        $(".error").text("")
                    }, 2000)
                }
            }
        })
    });

  

5,cookie与session保存验证码

   将随机验证码存储到session中,就是需要记录给哪个请求发了什么验证码。

  为什么这么说呢?因为到时候使用登录验证的使用者不止一个人,那么服务端发送的验证码不记录给哪个请求发送的验证码,当好几个人同时请求验证码信息,然后提交,这样就会发生混淆。所以保险起见,我们使用session保存验证码。

    views.py

 request.session['valid_code_str'] = valid_code_str

  login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <link rel="stylesheet" href="/static/blog/bootstrap-3.3.7-dist/css/bootstrap.css">

</head>
<body>
<h3 class=" text-center">登录页面</h3>
<div class="container">
    <div class="row">
        <div class="col-md-6 col-lg-offset-3">
            <form>
                {% csrf_token %}
                <div class="form-group">
                    <label for="user">用户名</label>
                    <input type="text" id="user" class="form-control">
                </div>
                <div class="form-group">
                    <label for="pwd">密码</label>
                    <input type="password" id="pwd" class="form-control">
                </div>

                <div class="form-group">
                    <label for="pwd">验证码</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 width="235" height="35" id="valid_code_img" src="/blog/get_validCode_image/" alt="">
                        </div>
                    </div>
                </div>

{#                <input type="submit" class="btn btn-default login_btn pull-right" value="submit">#}
                <input type="button" class="btn btn-default login_btn" value="submit"><span class="error"></span>
{#                <input type="button" class="btn btn-default login_btn pull-right" value="submit">#}
            </form>
        </div>
    </div>
</div>

<script src="/static/JS/jquery-3.2.1.js"></script>
<script>
    //刷新验证码
    $("#valid_code_img").click(function () {
        $(this)[0].src += "?"
    });

    // 登录验证
    $(".login_btn").click(function () {
        $.ajax({
            url: "",
            type: 'post',
            data: {
                user: $('#user').val(),
                pwd: $('#pwd').val(),
                valid_code: $("#valid_code").val(),
                csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val(),
            },
            success: function (data) {
                console.log(data);
                if (data.user){
                        if (location.search){
                            location.href = location.search.slice(6)
                        }
                        else {
                            location.href = '/blog/index/'
                        }
                }else {
                    $(".error").text(data.msg).css({'color':'red', 'margin-left':'10px'});
                    //  设置2秒后清空
                    setTimeout(function () {
                        $(".error").text("")
                    }, 2000)
                }
            }
        })
    });


</script>
</body>


</html>

  index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>Index Page</h1>
<p>{{ request.user.username }}</p>
</body>
</html>

  views.py

from django.shortcuts import render, HttpResponse, redirect

# Create your views here.
# from .MyForms import UserTestForm
# from .models import UserTest
from django.http import JsonResponse
from django.contrib import auth
import random


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 == valid_code_str:
    #     # 验证码不区分大小写
    #     if valid_code.upper() == valid_code_str:
    #         pass
    #     else:
    #         # 校验失败了。。。。
    #         response['msg'] = 'valid code error!'
    #         pass
    #     return JsonResponse(response)
    if request.method == 'POST':
        print("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 == valid_code_str:
        # 验证码不区分大小写
        if valid_code.upper() == valid_code_str.upper():
            user = auth.authenticate(username=user, password=pwd)
            if user:
                # request.user == 当前登录对象
                auth.login(request, user)
                response['user'] = user.username
                pass
            else:
                # response['msg'] = 'username or password error !'
                response['msg'] = '用户名或者密码错误'
        else:
            # 校验失败了。。。。
            response['msg'] = 'valid code error!'
        return JsonResponse(response)

    return render(request, 'login.html')

def get_validCode_image(request):
    from blog.utils.validCode import get_valid_code_img
    data = get_valid_code_img(request)
    return HttpResponse(data)




def index(request):
    return render(request, 'index.html')

  validCode.py

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):

    # # 方式一
    # with open('kd1.jpg', 'rb') as f:
    #     data = f.read()
    #
    # return HttpResponse(data)

    # # 方式二:使用pillow PIL模块
    # # pip  install pillow
    # from PIL import Image
    #
    # # img = Image.new("RGB", (270, 40), color='red')
    # img = Image.new("RGB", (270, 40), color=get_random_color())
    # with open("validCode.png", "wb") as f:
    #     img.save(f, 'png')
    # with open('validCode.png', 'rb') as f:
    #     data = f.read()
    # return HttpResponse(data)

    # 方式三,因为磁盘的方式比较慢,open是磁盘操作
    # 内存操作会比较快,这里使用内存操作
    # from PIL import Image, ImageDraw, ImageFont
    # from io import BytesIO
    #
    # img = Image.new('RGB', (270, 40), color=get_random_color())
    #
    # f = BytesIO()
    # img.save(f, 'png')
    # data = f.getvalue()


    # 方式四,图片里面什么都没,这里我们需要加上噪点,文字
    from PIL import Image, ImageDraw, ImageFont
    from io import BytesIO

    img = Image.new('RGB', (270, 40), color=get_random_color())
    draw = ImageDraw.Draw(img)
    vera_font = ImageFont.truetype("static/font/Vera.ttf", size=35)
    # char = str(random.randint(0, 9))

    # draw.text((0, 5), 'python', get_random_color(), font=vera_font)
    # draw.text((0, 5), char, get_random_color(), font=vera_font)
    #  ttf 字体下载
    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_upper_alpha, random_low_alpha])
        #  x, y  坐标
        draw.text((i*50+20, 5), random_char, get_random_color(), font=vera_font)
        # 保存验证码字符串
        valid_code_str += random_char

    width = 235
    height = 35
    for i in range(10):
        x1 = random.randint(0, width)
        x2 = random.randint(0, width)
        y1 = random.randint(0, height)
        y2 = random.randint(0, height)
        draw.line((x1, x2, y1, y2), fill=get_random_color())

    for i in range(40):
        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())

    print('valid_code_str', valid_code_str)

    request.session['valid_code_str'] = valid_code_str
    '''
    1, dasdasda
    2, COOKIE {'sessionid': dsdsadsdad}
    3,django-session 
        session-key  session-data  dsadasdsdsa
    4,
    '''
    f = BytesIO()
    img.save(f, 'png')
    data = f.getvalue()

    return data

  

验证码功能实现方法2——captcha

  在Django中实现图片验证码功能非常简单,有现成的第三方库可以使用,我们不必自己开发(但是也需要自己能开发的出来,方法二将自己开发的图片验证码模块)。这个库叫做django-simple-captcha。

1,安装 captcha

  直接使用pip 按照

pip  install django--simple-captcha

  

  Django 自动帮我们安装了相关的依赖库 six, olefile 和 pillow ,其中Pillow是大名鼎鼎的绘图模块。

2,注册captcha

  在settings.py中,将'captcha' 注册到APP列表里。

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'user19',
    'captcha',
]

  captcha 需要在数据库中建立自己的数据表,所以需要执行migrate命名生成数据表:

python manage.py makemigrations

python manage.py migrate

  

3,添加URL路由

  我们还需要在根目录下的urls.py文件添加 captcha 对应的网址:

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('blog/', include('blog.urls')),
    path('captcha', include('captcha.urls')),
]

  

4,修改 myforms.py

  如果上面都OK了,就可以直接在MyForms.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'}))
 
    password = forms.CharField(label="密码", max_length=256,
widget=forms.PasswordInput(attrs={'class': 'form-control'}))
 
    captcha = CaptchaField(label='验证码')

  注意:我们需要提前导入form captcha.fields import CaptchaField ,然后就像写普通的form字段一样添加一个captcha字段就可以了。

5,HTML文件的使用(修改 login.html文件)

  由于我们这里直接学习验证码,所以我这里直接写一个简单的login.html页面,添加 capthca的相关内容。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- 最新版本的 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">
</head>
<body>

{% block content %}
    <div class="container">
        <div class="col-md-4 col-md-offset-4">
          <form class='form-login' action="" method="post">
              {% csrf_token %}
              <h2 class="text-center">欢迎登录</h2>
              <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.errors }}
                  {{ login_form.captcha.label_tag }}
                  {{ login_form.captcha }}
              </div>

              <button type="submit" class="btn btn-primary pull-right">提交</button>

          </form>
        </div>
    </div>
{% endblock %}

</body>
</html>

  这里额外的添加了一条 {{ login_form.captcha.errors }} 用于明确指示用户,你的验证码不正确。其中验证图形码是否正确的工作都是在后台自动完成的。只需要使用is_valid()这个myforms内置的验证方法就一起进行了,完全不需要再视图函数中添加任何的验证代码,非常方便快捷!

6,查看效果

  直接的效果进入页面的效果如下:

  我们输入错验证码的效果如下:

   当然我们还可以添加多种效果,这里就不做添加了,就实现简单的验证码功能即可。

7,附带的代码

  models.py

class UserTest(models.Model):
    '''测试验证码,注册的用户表'''
    name = models.CharField(max_length=128)
    password = models.CharField(max_length=256)

    def __str__(self):
        return self.name

  views.py

def login_test(request):
    if request.method == 'POST':
        login_form = UserTestForm(request.POST)
        if login_form.is_valid():
            username = login_form.cleaned_data['username']
            password = login_form.cleaned_data['password']
            try:
                user = UserTest.objects.get(name=username)
                if user.password == password:
                    return HttpResponse("OK")
                else:
                    return HttpResponse("NG")
            except:
                return HttpResponse("NG")
        return render(request, 'login_test.html', locals())
    login_form = UserTestForm()
    return render(request, 'login_test.html', locals())

  

验证码功能实现方法3——极验验证SDK

一,Django极验滑动验证码的使用

1,官网直接注册账号申请key和value

  极验滑动验证码官网:www.geetest.com

2,从Github: gt3-python-sdk下载.zip文件

3,找到里面Django 的文件夹对照官网直接copy

4,代码

  views.py

from geetest import GeetestLib
from django.contrib import auth
from django.http import JsonResponse
from django.shortcuts import render
def login(request):
    if request.method == "POST":
        # 初始化一个给AJAX返回的数据
        ret = {"status": 0, "msg": ""}
        # 从提交过来的数据中 取到用户名和密码
        username = request.POST.get("username")
        pwd = request.POST.get("password")
        # 获取极验 滑动验证码相关的参数
        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)
        if result:
            # 验证码正确
            # 利用auth模块做用户名和密码的校验
            user = auth.authenticate(username=username, password=pwd)
            if user:
                # 用户名密码正确
                # 给用户做登录
                auth.login(request, user)  # 将登录用户赋值给 request.user
                ret["msg"] = "/index/"
            else:
                # 用户名密码错误
                ret["status"] = 1
                ret["msg"] = "用户名或密码错误!"
        else:
            ret["status"] = 1
            ret["msg"] = "验证码错误"

        return JsonResponse(ret)
    return render(request, "login.html")
# 请在官网申请ID使用,示例ID不可使用
pc_geetest_id = "b46d1900d0a894591916ea94ea91bd2c"
pc_geetest_key = "36fc3fe98530eea08dfc6ce76e3d24c4"


# 处理极验 获取验证码的视图
def get_geetest(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)

  urls.py

from django.conf.urls import url
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
  url(r'^login/', views.login),
    # 极验滑动验证码 获取验证码的url
    url(r'^pc-geetest/register', views.get_geetest),
]

  login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>欢迎登录</title>
    <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
    <link rel="stylesheet" href="/static/mystyle.css">
</head>
<body>

<div class="container">
    <div class="row">
        <form class="form-horizontal col-md-6 col-md-offset-3 login-form">
            {% csrf_token %}
            <div class="form-group">
                <label for="username" class="col-sm-2 control-label">用户名</label>
                <div class="col-sm-10">
                    <input type="text" class="form-control" id="username" name="username" placeholder="用户名">
                </div>
            </div>
            <div class="form-group">
                <label for="password" class="col-sm-2 control-label">密码</label>
                <div class="col-sm-10">
                    <input type="password" class="form-control" id="password" name="password" placeholder="密码">
                </div>
            </div>
            <div class="form-group">
                <!-- 放置极验的滑动验证码 -->
                <div id="popup-captcha"></div>
            </div>
            <div class="form-group">
                <div class="col-sm-offset-2 col-sm-10">
                    <button type="button" class="btn btn-default" id="login-button">登录</button>
                    <span class="login-error"></span>
                </div>
            </div>
        </form>
    </div>
</div>

<script src="/static/jquery-3.3.1.js"></script>
<script src="/static/bootstrap/js/bootstrap.min.js"></script>
<!-- 引入封装了failback的接口--initGeetest -->
<script src="http://static.geetest.com/static/tools/gt.js"></script>
<script>

    // 极验 发送登录数据的
    var handlerPopup = function (captchaObj) {
        // 成功的回调
        captchaObj.onSuccess(function () {
            var validate = captchaObj.getValidate();
            // 1. 取到用户填写的用户名和密码 -> 取input框的值
            var username = $("#username").val();
            var password = $("#password").val();
            $.ajax({
                url: "/login/", // 进行二次验证
                type: "post",
                dataType: "json",
                data: {
                    username: username,
                    password: password,
                    csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val(),
                    geetest_challenge: validate.geetest_challenge,
                    geetest_validate: validate.geetest_validate,
                    geetest_seccode: validate.geetest_seccode
                },
                success: function (data) {
                    console.log(data);
                    if (data.status) {
                        // 有错误,在页面上提示
                        $(".login-error").text(data.msg);
                    } else {
                        // 登陆成功
                        location.href = data.msg;
                    }
                }
            });
        });

         $("#login-button").click(function () {
            captchaObj.show();
        });
        // 将验证码加到id为captcha的元素里
        captchaObj.appendTo("#popup-captcha");
        // 更多接口参考:http://www.geetest.com/install/sections/idx-client-sdk.html
    };
    // 当input框获取焦点时将之前的错误清空
    $("#username,#password").focus(function () {
        // 将之前的错误清空
        $(".login-error").text("");
    });

    // 验证开始需要向网站主后台获取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>
</body>
</html>

  

知识储备:python中chr() 函数 和 ord() 函数的用法。

1,chr()函数

格式: Chr(<数值表达式>)

说明:chr() 用一个范围在 range(256)内的(就是0~255)整数做参数。函数返回值类型为String,其数值表达式值取值范围为0~255,返回一个对应的字符(对应的ASCII字符)。

例如:Print(Chr(78))  结果显示:N

65-90  大写A-Z

97-122 小写的a-z

2,ord() 函数

格式: ord("字符串")

说明:函数返回值类型为int

例如:Print(ord('0'))  结果显示:48

参考文献:https://www.cnblogs.com/chimeiwangliang/p/7130434.html

原文地址:https://www.cnblogs.com/wj-1314/p/10971846.html