2 基于用于认证组件 & ajax实现登录验证(图片验证码)

1 登录页面

settings.py
INSTALLED_APPS = [
    ...
    'blog.apps.BlogConfig',
]

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'HOST': '127.0.0.1',  # 数据库主机
        'PORT': 3306,  # 数据库端口
        'USER': 'root',  # 数据库用户名
        'PASSWORD': 'root123',  # 数据库用户密码
        'NAME': 'cnblog'  # 数据库名字
    }
}

STATIC_URL = '/static/'

# ============= 自个配置 ==============

AUTH_USER_MODEL = 'blog.UserInfo'

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static')
]
urls.py
from django.contrib import admin
from django.urls import path
from blog import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('login/', views.login),
]
views.py
from django.shortcuts import render

def login(request):
    return render(request, 'login.html')
login.html
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="{% static 'blog/css/bootstrap.css' %}">
</head>
<body>


<div class="container">
    <div class="row">
        <div class="col-md-6 col-lg-offset-3">
            <h3>登录页面</h3>
            <form>
                <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="form-control" id="valid_code">
                        </div>
                        <div class="col-md-6">
                            <img src="/get_validCode_img/" id="valid_code_img" width="260" height="32">
                        </div>
                    </div>
                </div>

                <input type="button" class="btn btn-default login_btn pull-right" value="登录">
            </form>
        </div>
    </div>
</div>

</body>
</html>

2 随机验证码实现

views.py
from django.shortcuts import render, HttpResponse, redirect
from PIL import Image, ImageDraw, ImageFont
from io import BytesIO
import random


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


def get_validCode_img(request):
    # 方式1:
    # with open('lulu.jpg', 'rb') as f:
    #     data = f.read()
    # return HttpResponse(data)

    # 方式2:pip install pillow
    # 磁盘管理
    # img = Image.new("RGB", (260, 32), 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:
    # 内存管理
    # img = Image.new("RGB", (260, 32), color=get_random_color())  # 图片句柄
    # f = BytesIO  # 内存句柄(使用完就会清除掉)
    # img.save(f, 'png')
    # data = f.getvalue()
    # return HttpResponse(data)

    # 方式4:面板里加内容
    # 内存管理
    img = Image.new("RGB", (260, 32), color=get_random_color())  # 图片句柄

    draw = ImageDraw.Draw(img)  # 生成画笔
    font_obj = ImageFont.truetype('static/blog/font/aigei_com.ttf', size=20)  # 字体样式的路径

    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=font_obj)  # 写文件
        # draw.line()  # 画线
        # draw.point()  # 画点

    width, height = 260, 40  # 设置图片的宽高
    for i in range(10):  # 造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(10):  # 造10个点
        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)


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

image


3 点击验证码刷新

根据以上login.html代码,在加入js代码即可

login.html
<script src="{% static 'blog/js/jquery-3.6.0.min.js' %}"></script>
<script>
    $("#valid_code_img").click(function () {
        $(this)[0].src += "?"
    })
</script>

4 验证码的存储

如果多人登录,那么验证码只能使最后一个人登录成功。这显然是有问题的,那么我们怎么解决呢?

解决方法:使用session,每个用户都有自己的session验证码。

views.py
from django.shortcuts import render, HttpResponse, redirect
from django.http import JsonResponse
from PIL import Image, ImageDraw, ImageFont
from io import BytesIO
import random


# Create your views here.


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


def get_validCode_img(request):
    ...

    request.session["valid_code_str"] = valid_code_str  # 将验证码存入用户session中
    '''
    session过程:
    1.生成一个随机的字符串 "asdfasdfsfsd"
    2.COOKIE  {'session_id': asdfasdfsfsd}
    3.在django-session表中生成
        session-key    session-data
        asdfasdfsfsd   {"valid_code_str": "xxxx"}
    '''

    f = 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():
            pass
        else:
            response['msg'] = "valid code error!"

        return JsonResponse(response)  # 使用JsonResponse返回的数据,前端直接可以使用。

    return render(request, 'login.html')

5 登录验证

views.py
from django.shortcuts import render
from django.http import JsonResponse
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 = request.POST.get('valid_code')
        valid_code_str = request.session.get("valid_code_str", '')

        if not valid_code.upper() == valid_code_str.upper():
            response['msg'] = "valid code error!"
            return JsonResponse(response)

        user = auth.authenticate(username=user, password=pwd)
        if not user:
            response['msg'] = "username or password error!"
            return JsonResponse(response)

        auth.login(request, user)  # request.user == 当前登录对象
        response['user'] = user.username

        return JsonResponse(response)  # 使用JsonResponse返回的数据,前端直接可以使用。

    return render(request, 'login.html')


def index(request):

    return render(request, 'index.html')
login.html
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="{% static 'blog/bootstrap/css/bootstrap.css' %}">
</head>
<body>


<div class="container">
    <div class="row">
        <div class="col-md-6 col-lg-offset-3">
            <h3>登录页面</h3>
            <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" class="form-control" id="valid_code">
                        </div>
                        <div class="col-md-6">
                            <img src="/get_validCode_img/" id="valid_code_img" width="260" height="32">
                        </div>
                    </div>
                </div>

                <input type="button" class="btn btn-default login_btn pull-right" value="登录">
                <span class="error" style="color: red"></span>
            </form>
        </div>
    </div>
</div>

<script src="{% static 'blog/js/jquery-3.6.0.min.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 (res) {
                if (res.user) {
                    location.href='/index/'
                }else {
                    $('.error').text(res.msg)
                }
            }
        })
    })

</script>

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

<h3>首页</h3>
<div>当前登录用户:{{ request.user.username }}</div>

</body>
</html>
posted @ 2022-08-12 15:57  角角边  Views(163)  Comments(0)    收藏  举报