基于Ajax与用户认证系统的登录验证

一、登录页面

from django.contrib import admin
from django.urls import path
from blog import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('login/', views.login),
]
urls.py

  创建login视图函数

from django.shortcuts import render

# Create your views here.


def login(request):
    return render(request, 'login.html')
views.py

  login.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录页面</title>
    <link rel="stylesheet" href="/static/blog/bootstrap-3.3.7/css/bootstrap.css">
</head>
<body>
<h3>登录页面</h3>
<div class="container">
    <div class="row">
        <div class="col-md-6 col-lg-offset-3">
            <form action="">
                <div class="form-group">
                    {# label标签的"for"属性可把label绑定到另外一个元素,因此要把for属性值与input的id属性相同。#}
                    {# 当用户选择该标签时,浏览器就会自动将焦点转到和标签相关的表单控件 #}
                    <label for="user">用户名</label>
                    {# 这里没必要加name属性了,之前加是点击submit按钮自己组装键值发出去,现在用ajax发只要找到标签拿到里面的值即可 #}
                    <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>
                {# 这里提交按钮不能使用<input type="submit">这就变成form表单提交事件了。 button类型时,这个按钮没有任何事件,可以给这个按钮绑定一个事件 #}
                <input type="button" class="btn btn-default login-btn pull-right" value="提交">
            </form>
        </div>
    </div>
</div>
</body>
</html>

注意:

  1、label标签的"for"属性可把label绑定到另外一个元素,因此要把for属性值与input的id属性相同。当用户选择该标签时,浏览器就会自动将焦点转到和标签相关的表单控件;

  2、这里没必要加name属性了,之前加是点击submit按钮自己组装键值发出去,现在用ajax发只要找到标签拿到里面的值即可。

  3、这里提交按钮不能使用<input type="submit">这样就变成form表单提交事件了。 设为button类型时,这个按钮没有任何事件,可以给这个按钮绑定一个事件

二、在页面中添加验证码图片请求路径

1、登录页面添加验证码

<div class="container">
    <div class="row">
        <div class="col-md-6 col-lg-offset-3">
            <form action="">
                <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" class="valid_code form-control">
                        </div>
                        <div class="col-md-6">
                            {# src还可以设置请求路径 #}
                            <img width="270" height="40" src="/get_validCode_img/" alt="">
                        </div>
                    </div>
                </div>
                <input type="button" class="btn btn-default login-btn pull-right" value="提交">
            </form>
        </div>
    </div>
</div>

  注意:<img src="">,src除了可以指定图片路径还是设置为请求路径。

2、验证码路由

path('get_validCode_img/', views.get_validCode_img),

三、验证码视图函数

1、方式一:读取静态图片文件

def get_validCode_img(request):
    with open("lufei.jpg", "rb") as f:
        data = f.read()

  显示效果如下:

  

  不推荐使用这种方法,验证图片不能仅仅指定一张图片,这种方法把程序写死了。

2、方式二:pillow生成动态图片

  生成动态随机图片,使用Python图像处理库:Pillow

  安装pillow库:pip3 install pillow

  引入Pillow中最重要的类Image,该类存在于同名的模块中。可以通过以下几种方式实例化:从文件中读取图片,处理其他图片得到,或者直接创建一个图片。

import random
def get_validCode_img(request):

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

    # 方式二:pip3 install pillow
    from PIL import Image
    img = Image.new("RGB", (270, 40), color=get_random_color())  # 得到img对象,颜色三要素:红绿蓝

    with open("validCode.png", "wb") as f:
        img.save(f, "png")    # 保存动态生成的图片

    with open("validCode.png", "rb") as f:
        data = f.read()

    return HttpResponse(data)

  运行效果如下:

  

  每次刷新,随机图片的颜色会发生随机变换。但是这种方式是请求进来时,先把数据加载到磁盘上,再在磁盘把数据读出来返还给浏览器,而且磁盘的处理数据时非常慢的,因此应该交到内存中管理。

3、方式三:使用pillow生成动态页面的基础上,引入BytesIO将图片保存在内存中

import random
def get_validCode_img(request):

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

    # 方式三:要引入BytesIO
    from PIL import Image
    from io import BytesIO
    img = Image.new("RGB", (270, 40), color=get_random_color())  # 得到img对象,颜色三要素:红绿蓝

    # f为内存句柄
    f= BytesIO()    # 会自己处理内存回收
    # 保存图片
    img.save(f, "png")
    data = f.getvalue()

    return HttpResponse(data)

4、方式四:添加验证码文字信息

  ImageDraw模块提供了图像对象的简单2D绘制。用户可以使用这个模块创建新的图像,注释或润饰已存在图像,为web应用实时产生各种图形。

draw.text()   写文字
        参数:  xy:坐标   text:文本内容   fill:文本颜色  font:文本样式
draw.line()   画线
draw.point()  画点

  ImageFont 模块中,可以使用 load() 函数加载一个 bitmap 字体,使用 truetype(fontfile, fontsize) 函数加载一个 OpenType/TrueType 字体(注意,这个函数需要额外安装_imageingft模块)。

  在static目录下创建font子目录,给用户存放字体文件。下载字体到该目录./cnblog/static/font/下。

import random
def get_validCode_img(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())  # 得到img对象,颜色三要素:红绿蓝
    # 创建Draw对象
    draw = ImageDraw.Draw(img)
    # 创建Font对象
    kumo_font = ImageFont.truetype("static/font/kumo.ttf", size=20)
    draw.text((0,5), "python", get_random_color(), font=kumo_font)
    f = BytesIO()   # f为内存句柄
    img.save(f, "png")
    data = f.getvalue()

    return HttpResponse(data)

  显示效果如下所示:

  

5、生成随机字符串验证码

  随机生成大写字母、小写字母、数字。

  针对随机字母需要用到chr()方法,用一个范围在 range(256)内的(就是0~255)整数作参数,返回一个对应的字符(当前整数对应的ascii字符)。

# 随机字母:
"""
>>> chr(65)
'A'
>>> chr(90)
'Z'
>>> chr(97)
'a'
>>> chr(122)
'z'
"""

  另外还需要用到choice() 方法,该方法可返回一个列表,元组或字符串的随机项。choice()是不能直接访问的,需要导入 random 模块,然后通过 random 静态对象调用该方法。

import random
def get_validCode_img(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())  # 得到img对象,颜色三要素:红绿蓝
    # 创建Draw对象
    draw = ImageDraw.Draw(img)
    # 创建Font对象
    kumo_font = ImageFont.truetype("static/font/kumo.ttf", size=28)

    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))   # 随机大写字母

        # 三选一:choice() 方法返回一个列表,元组或字符串的随机项。
        random_char = random.choice([random_num, random_low_alpha, random_upper_alpha])
        draw.text((i*50+20, 5), random_char, get_random_color(), font=kumo_font)  # 坐标错开间距

    f = BytesIO()  # f为内存句柄
    img.save(f, "png")
    data = f.getvalue()

    return HttpResponse(data)

  显示效果如下所示:

  

四、验证码图片的噪点和噪线

  添加图片噪点和噪线的代码:

# 给验证码图片添加噪点噪线
width = 270
height = 40
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, y1, x2, y2), fill = get_random_color())   # 画出一条线

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

  可以任意调配噪线和噪点的数量,尽量保证机器无法识别,但人可以识别。

  Draw 类提供了 arc(xy, start, end, options) 函数来绘制弧线,参数解析如下所示:

xy 是个长度为4的列表,用来表示一个 bounding box(边界区域)。如[x0, y0, x1, y1],分别表示 弧线最左侧距离左边、弧线最顶点距离上边、弧线最右侧距离左边、弧线最低点距离上边的距离。

start 和 end 则是弧的起止角度,单位是 °。其中水平向右的方向为 0°,竖直向下的方向为 90°,水平向左的方向为 180°,竖直向上的方向为 270°。

options 中可用选项:
    fill = (R, G, B) :指定线条颜色

  验证码视图修改如下:

import random
def get_validCode_img(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())  # 得到img对象,颜色三要素:红绿蓝
    # 创建Draw对象
    draw = ImageDraw.Draw(img)
    # 创建Font对象
    kumo_font = ImageFont.truetype("static/font/kumo.ttf", size=28)
        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))   # 随机大写字母

        # 三选一:choice() 方法返回一个列表,元组或字符串的随机项。注意:choice()是不能直接访问的,需要导入 random 模块,然后通过 random 静态对象调用该方法。
        random_char = random.choice([random_num, random_low_alpha, random_upper_alpha])
        draw.text((i*50+20, 5), random_char, get_random_color(), font=kumo_font)  # 坐标错开间距

    # 给验证码图片添加噪点噪线
    width = 270
    height = 40
    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, y1, x2, y2), fill = get_random_color())   # 画出一条线

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

    f = BytesIO()  # f为内存句柄
    img.save(f, "png")
    data = f.getvalue()

    return HttpResponse(data)

  显示效果如下所示:

  

五、验证码刷新功能

猜你喜欢

转载自www.cnblogs.com/xiugeng/p/9346269.html