django博客项目-登录验证码生成和登录校验

验证码图片生成

图片背景随机生成

验证码图片每次登录的时候都会刷新不同的验证码,有两种方式:

  • 本地存储所有验证码图片,每次返回本地验证码图片,很占资源,不建议使用
  • 后台自动生成验证码图片,每次返回随机生成的图片
login.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>blog</title>
    <link rel="stylesheet" href="/static/css/bootstrap.min.css">
    <script src="/static/js/bootstrap.min.js"></script>
</head>
<body>
<h1>登录</h1>
<div class="row">
    <div class="col-md-6 col-lh-offset-3">
        <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="valid">验证码</label>
                <div class="row">
                    <div class="col-md-6">
                        <input type="txt" class="valid_code form-control">
                    </div>
                    <div class="col-md-6">
                        <img width="270" height="40" id="valid_code_img" src="/get_validCode_img">
                    </div>

                </div>

            </div>
        </form>

    </div>
</div>


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

</script>
</body>
</html>
# views.py
def get_validCode_img(request):
    def get_random_color():
        return random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)
    # 方式一
    # with open('dog.jpg') as f:
    #     data = f.read()

    # 方式二 pillow 模块
    # 使用磁盘作为存储,每次都需要写入文件打开文件,IO磁盘操作都是很慢的
    # from PIL import Image
    # img = Image.new('RGB', (270, 40), (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)))
    #
    # with open('validCode.png', 'wb') as f:
    #     img.save(f, 'png')
    #
    # with open('validCode.png', 'rb') as f:
    #     data = f.read()

    # 方式3 使用内存句柄,不经过磁盘
    from PIL import Image, ImageDraw, ImageFont
    from io import BytesIO
    img = Image.new('RGB', (270, 40), get_random_color())

    # 在图片上增加文字
    draw = ImageDraw.Draw(img)
    halfings_font = ImageFont.truetype("static/fonts/kumo.ttf", size=32)
    # 随机字符生成
    for i in range(5):
        random_number = str(random.randint(0, 9))
        random_low_alpha = chr(random.randint(97, 122))
        random_upper_alpha = chr(random.randint(65,90))
        random_char = random.choice([random_low_alpha, random_number, random_upper_alpha])
        draw.text((i*50+20, 5), random_char, get_random_color(), font=halfings_font)

    # 噪点噪线
    width = 270
    height = 40
    # 划线
    for i in range(5):
        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(30):
        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)

知识点

PIL 模块使用
BytesIO 模块使用

效果展示

在这里插入图片描述

验证码校验

思路:在生成验证码图片的时候,需将生成的校验码保存到session中,保证每个用户之间的校验码是单独的,互不影响。在校验用户输入的时候将其从session中拿出来校验即可。
登录点击使用ajax来完成,对数据校验之后出现的错误数据进行局部显示,用来提示用户。
前端代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>blog</title>
    <link rel="stylesheet" href="/static/css/bootstrap.min.css">
    <script src="/static/js/bootstrap.min.js"></script>
</head>
<body>
<h1>登录</h1>
<div class="row">
    <div class="col-md-6 col-lh-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="valid">验证码</label>
                <div class="row">
                    <div class="col-md-6">
                        <input type="txt" class="form-control" id="valid_code">
                    </div>
                    <div class="col-md-6">
                        <img width="270" height="40" id="valid_code_img" src="/get_validCode_img">
                    </div>

                </div>

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

            </div>
        </form>

    </div>
</div>


<script src="/static/js/jquery.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(data){
                console.log(data)
            }
        })
    })

</script>
</body>
</html>

后端代码

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.lower() == valid_code_str.lower():
            # 用户名密码校验
            pass
        else:
            response['msg'] = 'valid code error'

        print(user, pwd, valid_code)
        return JsonResponse(response)

    return render(request, 'login.html')

def get_validCode_img(request):
    def get_random_color():
        return random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)
    # 方式3 使用内存句柄,不经过磁盘
    from PIL import Image, ImageDraw, ImageFont
    from io import BytesIO
    img = Image.new('RGB', (270, 40), get_random_color())

    # 在图片上增加文字
    draw = ImageDraw.Draw(img)
    halfings_font = ImageFont.truetype("static/fonts/kumo.ttf", size=32)
    # 保存生成的随机验证码
    valid_code_str = ''
    # 随机字符生成
    for i in range(5):
        random_number = str(random.randint(0, 9))
        random_low_alpha = chr(random.randint(97, 122))
        random_upper_alpha = chr(random.randint(65,90))
        random_char = random.choice([random_low_alpha, random_number, random_upper_alpha])
        draw.text((i*50+20, 5), random_char, get_random_color(), font=halfings_font)
        valid_code_str += random_char

    # 存储生成验证码到session中,保证每一个人的都是独立的
    request.session['valid_code_str'] = valid_code_str

    # 噪点噪线
    width = 270
    height = 40
    # 划线
    for i in range(5):
        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(30):
        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)

用到的知识点

request.session

	request.session[''key] = value  存储数据到session中
	request.session.get('key')  获取session中的数据

ajax

	css结合ajax增加点击事件:
		<input type="button" class="btn btn-default login_btn pull-right" value="登录">
		$('.login_btn').click(function () {}
	ajax成功函数中的log显示:
		console.log(data)
	ajax获取name为某固定值的标签的value内容
		$("[name='csrfmiddlewaretoken']").val()

前端效果展示

在这里插入图片描述

登录校验

使用auth模块做用户认证功能,当用户认证成功后,需对当前用户进行注册,request.user就等于了当前登录用户,并且全局可以用。
前端代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>blog</title>
    <link rel="stylesheet" href="/static/css/bootstrap.min.css">
    <script src="/static/js/bootstrap.min.js"></script>
</head>
<body>
<h1>登录</h1>
<div class="row">
    <div class="col-md-6 col-lh-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="valid">验证码</label>
                <div class="row">
                    <div class="col-md-6">
                        <input type="txt" class="form-control" id="valid_code">
                    </div>
                    <div class="col-md-6">
                        <img width="270" height="40" id="valid_code_img" src="/get_validCode_img">
                    </div>

                </div>

            </div>
            <div class="form-group">
                <input type="button" class="btn btn-default login_btn" value="登录">
                <span id="error_info"></span>

            </div>
        </form>

    </div>
</div>


<script src="/static/js/jquery.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(data){
                console.log(data)
                if (data.user){
                // 用户成功登录之后的跳转
                    location.href = "/index"
                }
                else {
                // 显示错误信息,text修改标签之间的内容,css增加css样式
                    $('#error_info').text(data.msg).css({"color":"red", "margin-left":"20px"})
                    // 定时任务,多久之后执行对应函数。对错误信息显示后自动消失
                    setTimeout(function (){
                        $('#error_info').text("")
                    }, 1000)
                }
                }
            }
        })
    })

</script>
</body>
</html>

后端代码:

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.lower() == valid_code_str.lower():
            # 用户名密码校验
            login_user = auth.authenticate(username=user, password=pwd)
            if login_user:
                # 用户校验成功,进行注册,request.user== 当前登录对象,丙炔全局可用
                auth.login(request, login_user)
                response['user'] = login_user.username
            else:
                response['msg'] = 'username or password error'
        else:
            response['msg'] = 'valid code error'

        print(user, pwd, valid_code)
        return JsonResponse(response)

    return render(request, 'login.html')

用到的知识点

auth模块的使用
ajax对标签内容的替换和前端跳转
ajax定时多久执行函数

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值