2-功能1:基于用户认证组件和Ajax实现登录验证(图片验证码)

 

 

1、登录页面的设计

 (1)label标签的id属性

label标签的id属性,点击label标记,相当于点击了input框

bootstarp样式
    class="form-group"
    class="form-control"

 

(2)此时的验证码先取静态路径

 

 

                <div class="form-group">
                    <label for="id_valid_code_str">验证码</label>
                    <div class="row">
                        <div class="col-md-6">
                            <input type="text" id="id_valid_code_str" class="form-control">
                        </div>
                        <div class="col-md-6">
                            <img src="/blog/get_validCode/" id="id_valid_code_img" width="270" height="35" title="验证码" alt="">
                        </div>
                    </div>
                </div>

 

 2、验证码图片的生成

 

 

 

(1)方式1:HttpResponse返回字符串



(2)方式2:引入PIL模块  pip install pillow

from PIL import Image
import random


def get_random_color():
    """生成随机颜色(255,255,255)"""
    return tuple([random.randint(0, 255) for _ in range(3)])


def get_validCode(request):
    # 在本地生成一张图片validCode.png
    img = Image.new("RGB", (270, 35), 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)

 

 

 (3)方式3:内存处理

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


def get_random_color():
    """生成随机颜色(255,255,255)"""
    return tuple([random.randint(0, 255) for _ in range(3)])


def get_validCode(request):
    
    # 在内存生成一张图片validCode.png
    img = Image.new('RGB', (210, 35), color=get_random_color())
    f = BytesIO()
    img.save(f, 'png')
    data = f.getvalue()

    return HttpResponse(data)

 

 

(4)方式4:加入噪点的,字体的

# 方式4:加入噪点的
from PIL import Image, ImageDraw, ImageFont
from io import BytesIO
import random
import string   # string字符串

def get_random_color():
    return tuple([random.randint(0, 255) for _ in range(3)])


def get_validCode(request):
    holly_font = ImageFont.truetype('static/font/holly.ttf', size=28)  # 字体

    img = Image.new('RGB', (210, 35), color=get_random_color())
    draw = ImageDraw.Draw(img)  # 在img上作画

    # draw.text()     # 文字
    # draw.line()     # 线
    # draw.point()    # 点

    # draw数字字母5个
    for i in range(5):
        random_char = random.choice(string.digits + string.ascii_letters)
        draw.text((i * 40 + 20, 5), random_char, get_random_color(), font=holly_font)

    # 补充噪点噪音
    width, height = 210, 35
    for i in range(100):
        x1 = random.randint(0, width)
        x2 = random.randint(0, width)
        y1 = random.randint(0, width)
        y2 = random.randint(0, width)
        draw.line((x1, y1, x2, 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())

    # 内存处理
    f = BytesIO()
    img.save(f, 'png')
    data = f.getvalue()

    return HttpResponse(data)

    

 

 

 3、验证码的刷新与字符串保存,验证码解耦

(1)刷新

 

$("#id_valid_code_img")
[img#id_valid_code_img]
$("#id_valid_code_img")[0]
<img src=​"/​blog/​get_validCode/​" id=​"id_valid_code_img" width=​"270" height=​"35" title=​"验证码" alt>​
$("#id_valid_code_img")[0].src
"http://127.0.0.1:8000/blog/get_validCode/"
$("#id_valid_code_img")[0].src+="?"    # 页面刷新
"http://127.0.0.1:8000/blog/get_validCode/?"  
$("#id_valid_code_img")[0].src+="?"
"http://127.0.0.1:8000/blog/get_validCode/??"
$("#id_valid_code_img")[0].src+="?"
"http://127.0.0.1:8000/blog/get_validCode/???"

 

 

 模板层 js代码

<script type="text/javascript">
    //刷新验证码
    $(function () {
        $("#id_valid_code_img").click(function () {
            $(this)[0].src+="?"
        })
    })
</script>

 

(2)保存验证码字符串

 

 

(3)多个用户同时访问验证码

全局变量不可取

 

(4)session存储验证码字符串

 

 

 

 (5)验证码解耦

 

validCode.py

# 方式4:加入噪点的
from PIL import Image, ImageDraw, ImageFont
from io import BytesIO
import random
import string  # string字符串


def get_random_color():
    return tuple([random.randint(0, 255) for _ in range(3)])


def get_validCode_img(request):
    holly_font = ImageFont.truetype('static/font/holly.ttf', size=28)  # 字体

    img = Image.new('RGB', (210, 35), color=get_random_color())
    draw = ImageDraw.Draw(img)  # 在img上作画

    # draw数字字母5个
    valid_code_str = ""  # 保存验证码字符串
    for i in range(5):
        random_char = random.choice(string.digits + string.ascii_letters)
        draw.text((i * 40 + 20, 5), random_char, get_random_color(), font=holly_font)
        valid_code_str += random_char

    print("valid_code_str", valid_code_str)

    # 把验证码放入session中
    request.session["valid_code_str"] = valid_code_str

    # 内存处理
    f = BytesIO()
    img.save(f, 'png')
    data = f.getvalue()

    return data

 

 

 views.py视图

from django.shortcuts import render, HttpResponse, redirect
from blog.utils.validCode import get_validCode_img      # 导入验证码函数


def login(request):
    return render(request, 'blog/login.html')


def get_validCode(request):
    """
    基于PIL模块动态生成响应状态码图片
    :param request: 
    :return: 
    """
    data = get_validCode_img(request)
    return HttpResponse(data)

 

 

 

4、登录验证 

(1)ajax流程图

 

(2)用户认证auth模块,ajax信息response

 

(3)ajax  success成功执行

 

 

 

 

 

 

   (4)代码优化:错误信息1s后消失

 (5)完整代码

主url

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

urlpatterns = [
    path('admin/', admin.site.urls),
    re_path(r'^blog/', include(('blog.urls', 'blog')))
]
View Code

 

url

from django.urls import path, re_path
from blog import views
from django.views.static import serve
from cnblog import settings

urlpatterns = [
    re_path('^login/$', views.login, name='login'),
    re_path('^get_validCode/$', views.get_validCode, name='get_validCode'),
    re_path('^index/$', views.index, name='index'),
]

 

 

view视图

from django.shortcuts import render, HttpResponse, redirect
from blog.utils.validCode import get_validCode_img  # 导入验证码函数
from django.http import JsonResponse  # Json数据返回到前端
from django.contrib import auth     # 用户认证组件


def login(request):
    if request.method == "POST":
        response = {'user': None, "msg": None}
        user = request.POST.get("user")
        pwd = request.POST.get("pwd")
        valid_code_str = request.POST.get("valid_code_str")

        _valid_code_str = request.session.get("valid_code_str")

        # 验证码验证
        if valid_code_str.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, 'blog/login.html')


def get_validCode(request):
    """
    基于PIL模块动态生成响应状态码图片
    :param request:
    :return:
    """
    data = get_validCode_img(request)
    return HttpResponse(data)

def index(request): return HttpResponse(request.user.username)

 

 

 

utils工具包:验证码解耦

# 方式4:加入噪点的
from PIL import Image, ImageDraw, ImageFont
from io import BytesIO
import random
import string  # string字符串


def get_random_color():
    return tuple([random.randint(0, 255) for _ in range(3)])


def get_validCode_img(request):
    holly_font = ImageFont.truetype('static/font/holly.ttf', size=28)  # 字体

    img = Image.new('RGB', (210, 35), color=get_random_color())
    draw = ImageDraw.Draw(img)  # 在img上作画

    # draw数字字母5个
    valid_code_str = ""  # 保存验证码字符串
    for i in range(5):
        random_char = random.choice(string.digits + string.ascii_letters)
        draw.text((i * 40 + 20, 5), random_char, get_random_color(), font=holly_font)
        valid_code_str += random_char

    print("valid_code_str", valid_code_str)

    # 把验证码放入session中
    request.session["valid_code_str"] = valid_code_str

    # 内存处理
    f = BytesIO()
    img.save(f, 'png')
    data = f.getvalue()

    return data

 

 

模板层

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/static/blog/bs/css/bootstrap.css">
    <script src="/static/js/jquery-3.2.1.min.js"></script>
</head>
<body>

<h3>登录页面</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="id_username">用户名</label>
                    <input type="text" id="id_username" class="form-control">
                </div>
                <div class="form-group">
                    <label for="id_password">密码</label>
                    <input type="password" id="id_password" class="form-control">
                </div>
                <div class="form-group">
                    <label for="id_valid_code_str">验证码</label>
                    <div class="row">
                        <div class="col-md-6">
                            <input type="text" id="id_valid_code_str" class="form-control">
                        </div>
                        <div class="col-md-6">
                            <img src="/blog/get_validCode/" id="id_valid_code_img" width="270" height="35" title="验证码"
                                 alt="">
                        </div>
                    </div>
                </div>
                <input type="button" class="btn btn-default login-btn" value="登录"><span class="error"></span>

            </form>
        </div>
    </div>
</div>
</body>

</html>

 

 

ajax代码

<script type="text/javascript">
    //刷新验证码
    $(function () {
        $("#id_valid_code_img").click(function () {
            $(this)[0].src += "?"
        })
    });

    //登录验证
    $(function () {
        $('.login-btn').click(function () {
            $.ajax({
                url: '',
                type: 'post',
                data: {
                    user: $("#id_username").val(),
                    pwd: $("#id_password").val(),
                    valid_code_str: $("#id_valid_code_str").val(),
                    csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val()

                },
                success: function (data) {
                    console.log(data)

                    if (data.user) {
                        location.href = "/blog/index"
                    }
                    else {
                        $('.error').text(data.msg).css({'color': 'red', 'margin-left': '20px'});

                        //定时器 1s后error_msg 消失
                        setTimeout(function () {
                            $('.error').text("")
                        }, 1000)
                    }
                }

            })
        })
    })
</script>

 

 

 

 (6)滑动验证码:django-demo

 

 

 

 

 

   (7)总结

总结: 
   1 一次请求伴随多次请求

   2 PIL     
        # 生成验证码图片

   3 session存储  
        # 把验证码放入session中
        request.session["valid_code_str"] = valid_code_str

   4 验证码刷新    
        //刷新验证码
        $(function () {
            $("#id_valid_code_img").click(function () {
                $(this)[0].src += "?"
            })
        });    

 

 

 

posted @ 2018-07-25 14:59  venicid  阅读(732)  评论(0编辑  收藏  举报