BBS - 登錄頁 - 驗證碼

 

 

  基於用戶認證組件和Ajax實現登陸驗證(圖片驗證碼)

  UserInfo表既有原生auth_user表的字段,又有你擴展的字段,之後用的接口UserInfo既是本身的用戶表又是原生認證組件的用戶表css

一.登陸頁面的設計

  login.htmlhtml

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

    <h3>登陸頁面</h3>

    <div class="container">
        <div class="row">
            <div class="col-md-6 col-md-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="">驗證碼</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="265" height="38" id="valid_code_img" src="/get_valid_img/" alt="">
                            </div>
                        </div>
                    </div>
                    <input type="button" class="btn btn-default login_btn " value="submit"><span class="error"></span>
                    <a href="/register/" class="btn btn-success pull-right">註冊</a>
                </form>
            </div>
        </div>
    </div>

 

二.驗證碼圖片的生成

  validCode.pyjquery

# -*- coding:utf-8 -*-
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("kobe.jpg", "rb") as f:
    #     data = f.read()
    # return HttpResponse(data)

    # 方式二:磁盤中 速度慢 # pip install pillow # 圖像處理模塊
    # from PIL import Image
    # img = Image.new("RGB", (265, 38), color=get_random_color())  # Image.new(mode,size,color) 長度265 高度38
    #
    # # 生成隨機圖片
    # with open("validCode.png", "wb") as f: # 先加到磁盤上
    #     img.save(f, "png")  # 會生成一個叫validCode.png的圖片
    #
    # # 讀出圖片
    # with open("validCode.png", "rb") as f:
    #     data = f.read()

    # 方式三:放在內存中
    # from PIL import Image
    # from io import BytesIO   # BytesIO就是內存管理
    # img = Image.new("RGB", (265, 38), color=get_random_color())  # Image.new(mode,size,color)
    #
    # f = BytesIO()  # 內存句柄
    # img.save(f, "png")  # save到內存中
    # data = f.getvalue()  # 讀數據

    # 方式四:放在內存中, 添加文字
    from PIL import Image, ImageDraw, ImageFont  # ImageDraw是畫筆,ImageFont是字體大小
    from io import BytesIO
    img = Image.new("RGB", (265, 38), color=get_random_color())  # Image.new(mode,size,color)

    draw = ImageDraw.Draw(img)  # 在img中畫東西,draw.text()寫文字,draw.line()畫線,draw.point()畫點
    kumo_font = ImageFont.truetype("static/fonts/KumoFont.ttf", size=30) # 參數爲字體路徑和大小

    # global valid_code_str
    valid_code_str = ""
    for i in range(6):
        random_num = 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_num, random_low_alpha, random_upper_alpha])

        # text(self, xy, text, fill=None, font=None, anchor=None,*args, **kwargs)
        # xy:座標 text:文字 fill:顏色 font:字體
        draw.text(((30*i+45), 5), random_char, get_random_color(), font=kumo_font)

        # 保存驗證碼字符串
        valid_code_str += random_char

    f = BytesIO()  # 內存句柄
    img.save(f, "png")
    data = f.getvalue()  # 讀數據

    return data

噪聲噪線

  validCode.pyajax

補充躁點躁線, 防止機器
    width = 265  # 要跟上邊的寬高一致
    height = 38

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

三.驗證碼刷新

$("#valid_code_img")[0]
<img width=​"270" height=​"40" id=​"valid_code_img" src=​"http:​/​/​127.0.0.1:​8000/​get_validCode_img/​??" alt>​
 $("#valid_code_img")[0].src
"http://127.0.0.1:8000/get_validCode_img/??"

 $("#valid_code_img")[0].src+="?"  #+="?"添加一次這個就刷新一次驗證碼
"http://127.0.0.1:8000/get_validCode_img/???"
 $("#valid_code_img")[0].src+="?"
"http://127.0.0.1:8000/get_validCode_img/????"
 $("#valid_code_img")[0].src+="?"
"http://127.0.0.1:8000/get_validCode_img/?????"
 $("#valid_code_img")[0].src+="?"
"http://127.0.0.1:8000/get_validCode_img/??????"
 $("#valid_code_img")[0].src+="?"
"http://127.0.0.1:8000/get_validCode_img/???????"

  login.htmldjango

<script src="/static/js/jquery-3.3.1.js"></script>
    <script>
        {# 刷新驗證碼,不用ajax也能夠 #}
        $("#valid_code_img").click(function () {
            $(this)[0].src += "?"
        });
    </script>

四.保存驗證碼字符串

   validCode.pybootstrap

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_low_alpha, random_upper_alpha])
        draw.text((i*50+20, 5), random_char, get_random_color(), font=kumo_font)

        #保存驗證碼字符串
        valid_code_str += random_char #作一個累加

    print("valid_code_str", valid_code_str)
    request.session["valid_code_str"] = valid_code_str  #保存它,寫一個session

    '''
    1 sdajsdq33asdf #生成一個隨機字符串,
    2 COOKIE {"sessionid":sdajsdq33asdf} #設置一個cookie,返回給cookie那邊一個鍵叫sessionid,值是隨機字符串
    3 django-session   #數據部分保存到了django_session;在session表進行存儲
      session-key   session-data
      sdajsdq33asdf  {"valid_code_str":"12345"}
    '''

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

    return HttpResponse(data)

五.登陸驗證

#global valid_code_str 這裏不能把它變成全局變量,這時雖然校驗時能夠拿到valid_code_str,但若是是兩我的一塊訪問,那麼那個驗證碼的值存的是最後一我的訪問(刷新)的,前面那我的那個就取不到了應該每一個人的單獨保存,使用會話跟蹤技術,把每一個人校驗的值存到cookie裏邊

  views.py

# -*- encoding:utf-8 -*-
from django.shortcuts import render, HttpResponse, redirect

import random
# Create your views here.
from django.http import JsonResponse
from django.contrib import auth

def login(request):

    if request.method == "POST":

        response = {"user": None, "msg": None} # 先構建一個字典,"user":None默認沒有登陸成功,"msg"裏邊放錯誤信息
        user = request.POST.get("user")
        pwd = request.POST.get("pwd")
        valid_code = request.POST.get("valid_code")

        # global valid_code_str,不能使用這種方法,由於當多我的同時登陸的時候valid_code_str會被覆蓋掉,會產生混淆
        # 使用會話跟蹤技術,session來保存每一個人的驗證碼,request.session["valid_code_str"] = valid_code_str
        valid_code_str = request.session.get("valid_code_str")         if valid_code.upper() == valid_code_str.upper():    # 驗證驗證碼,不區分大小寫

            #  驗證用戶名密碼
            user = auth.authenticate(username=user, password=pwd) # 用戶認證組件
            if user:  # 把這個user註冊進去,只要登陸成功了,request.user就是當前登陸對象用戶,不然它就是個匿名對象
                auth.login(request, user)  # requese.user 當前登陸對象,登陸成功在這裏不能跳轉,用的是ajax請求而不是form請求,ajax請求只接收一個數據data
                response["user"] = user.username
            else:
                response["msg"] = "用戶名或者密碼錯誤!"
        else:
            response["msg"] = "驗證碼錯誤!"

        return JsonResponse(response) # 直接把字典放裏面,它幫咱們序列化,並且在ajax那邊直接拿到對象也不用反序列化

    return render(request, 'login.html')

def index(request):

    return render(request, "index.html")

 

  login.htmlcookie

 

 

{# ajax登陸驗證 #}
        $(".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/" {# 登陸成功就跳轉到index頁面 #}
                    }
                    else {
                        $(".error").text(data.msg).css({"color": "red", "margin-left":"20px"})

                        {# 規定時間清空錯誤信息 #}
                        setTimeout(function () {
                            $(".error").text("")
                        }, 1000)
                    }
                }
            })
        })

 

總結:
1 一次請求伴隨屢次請求
2 PIL
3 session存儲
4 驗證碼刷新

 

 

附:

 

滑動驗證碼--->引入這樣一個插件session

 

要先把social-auth-app-django下載下來app

 

C:\Users\Administrator>pip install social-auth-app-django
Collecting social-auth-app-django

 

 

把它嵌入到咱們的代碼裏邊dom

 

相關文章
相關標籤/搜索