Django+Jquery+Ajax+驗(yàn)證碼登錄案例系列之十二

1,創(chuàng)建項(xiàng)目test04

這里寫(xiě)圖片描述

2,創(chuàng)建應(yīng)用app為booktest

這里寫(xiě)圖片描述

3,注冊(cè)應(yīng)用booktest

作用讓創(chuàng)建的應(yīng)用運(yùn)行起來(lái)

這里寫(xiě)圖片描述

4,在項(xiàng)目根目錄下創(chuàng)建模板templates目錄

  • 作用就是存放html文件
這里寫(xiě)圖片描述
  • 在項(xiàng)目的settings.py文件中配置模板,如下圖:
這里寫(xiě)圖片描述

5,在項(xiàng)目根目錄下創(chuàng)建static目錄

  • 作用就是存放css/圖片/js等文件
這里寫(xiě)圖片描述
  • 在項(xiàng)目的settings.py文件中配置static文件,如下圖
這里寫(xiě)圖片描述

6,數(shù)據(jù)庫(kù)的創(chuàng)建與配置

這里寫(xiě)圖片描述

手動(dòng)的在mysql數(shù)據(jù)庫(kù)中創(chuàng)建test04數(shù)據(jù)庫(kù),如下圖

這里寫(xiě)圖片描述

7,DEBUG開(kāi)關(guān)設(shè)置

這里寫(xiě)圖片描述

8,設(shè)置編碼和時(shí)間

LANGUAGE_CODE = 'zh-Hans'

TIME_ZONE = 'Asia/Shanghai'

9,項(xiàng)目的urls文件中配置如下:

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^',include('booktest.urls'))
]

10,在booktest應(yīng)用下創(chuàng)建urls目錄并配置

from django.conf.urls import url
from  booktest import views

urlpatterns = [
    # 登錄成功url
    url(r'^success/$', views.success),
    # ajax登錄url
    url(r'^login_ajax/$', views.login_ajax),
    # ajax登錄校驗(yàn)url
    url(r'^login_ajax_check/$', views.login_ajax_check),
    # 生產(chǎn)驗(yàn)證碼圖片url
    url(r'^verify_code/$', views.verify_code),
    # 發(fā)帖頁(yè)面url
    url(r'^post_article/$', views.post_article), 
]

11,在booktest應(yīng)用views中創(chuàng)建各個(gè)視圖函數(shù)

from django.shortcuts import render
from django.http import JsonResponse
# PIL是python2版本的圖像處理庫(kù),不過(guò)現(xiàn)在用Pillow比PIL強(qiáng)大,是python3的處理庫(kù)
from PIL import Image, ImageDraw, ImageFont
from django.http import HttpResponse
from django.shortcuts import render, redirect
import random
# 在python2.x中導(dǎo)入模塊方法:
# from StringIO import String
# 在python2.x中它還有個(gè)孿生兄弟,運(yùn)行速度比它快,用c實(shí)現(xiàn)的
# from cStringIO import StringIO

# 在python3.x中,StringIO已經(jīng)在io模塊中了,導(dǎo)入方法
from io import BytesIO


# ajax登錄視圖函數(shù)
def login_ajax(request):
    return render(request, 'booktest/login_ajax.html')


# ajax登錄校驗(yàn)回調(diào)視圖函數(shù)
def login_ajax_check(request):
    # 1,獲取用戶輸入的用戶名和密碼
    uname = request.POST.get('uname')
    password = request.POST.get('password')
    # 獲取用戶輸入的驗(yàn)證碼
    vcode = request.POST.get('vcode')
    # 獲取session中的驗(yàn)證碼
    vcode_session = request.session.get('verifycode')

    # 2,用戶名和密碼校驗(yàn)
    if uname == 'xiaoke' and password == '123456' and vcode == vcode_session:
        # 保存用戶的登錄狀態(tài)
        request.session['isLogin']=True
        request.session['uname']=uname
        request.session['password']=password
        return JsonResponse({'msg': 'ok'})
    elif uname != 'xiaoke' or password != '123456':
        return JsonResponse({'msg': 'fail_user'})
    elif vcode != vcode_session:
        return JsonResponse({'msg': 'fail_verify'})


def verify_code(request):
    # 1,定義變量,用于畫(huà)面的背景色、寬、高
    # random.randrange(20, 100)意思是在20到100之間隨機(jī)找一個(gè)數(shù)
    bgcolor = (random.randrange(20, 100), random.randrange(20, 100), 255)
    width = 100
    height = 25
    # 2,創(chuàng)建畫(huà)面對(duì)象
    im = Image.new('RGB', (width, height), bgcolor)
    # 3,創(chuàng)建畫(huà)筆對(duì)象
    draw = ImageDraw.Draw(im)
    # 4,調(diào)用畫(huà)筆的point()函數(shù)繪制噪點(diǎn),防止攻擊
    for i in range(0, 100):
        # 噪點(diǎn)繪制的范圍
        xy = (random.randrange(0, width), random.randrange(0, height))
        # 噪點(diǎn)的隨機(jī)顏色
        fill = (random.randrange(0, 255), 255, random.randrange(0, 255))
        # 繪制出噪點(diǎn)
        draw.point(xy, fill=fill)
    # 5,定義驗(yàn)證碼的備選值
    str1 = 'ABCD123EFGHIJK456LMNOPQRS789TUVWXYZ0'
    # 6,隨機(jī)選取4個(gè)值作為驗(yàn)證碼
    rand_str = ''
    for i in range(0, 4):
        rand_str += str1[random.randrange(0, len(str1))]
    # 7,構(gòu)造字體對(duì)象,ubuntu的字體路徑為“/usr/share/fonts/truetype/freefont”
    font = ImageFont.truetype('FreeMono.ttf', 23)
    # 8,構(gòu)造字體顏色
    fontcolor = (255, random.randrange(0, 255), random.randrange(0, 255))
    # 9,繪制4個(gè)字
    draw.text((5, 2), rand_str[0], font=font, fill=fontcolor)
    draw.text((25, 2), rand_str[1], font=font, fill=fontcolor)
    draw.text((50, 2), rand_str[2], font=font, fill=fontcolor)
    draw.text((75, 2), rand_str[3], font=font, fill=fontcolor)
    # 9,用完畫(huà)筆,釋放畫(huà)筆
    del draw
    # 10,存入session,用于做進(jìn)一步驗(yàn)證
    request.session['verifycode'] = rand_str
    # 11,內(nèi)存文件操作
    buf = BytesIO()
    # 12,將圖片保存在內(nèi)存中,文件類(lèi)型為png
    im.save(buf, 'png')
    # 13,將內(nèi)存中的圖片數(shù)據(jù)返回給客戶端,MIME類(lèi)型為圖片png
    return HttpResponse(buf.getvalue(), 'image/png')


# ajax登錄成功視圖函數(shù)
def success(request):
    # 用戶已經(jīng)登錄
    if request.session.get('isLogin'):
        return render(request, 'booktest/success.html')
    else:
        return redirect('/login_ajax/')

# 發(fā)帖操作視圖函數(shù)
def post_article(request):
    # 獲取登錄的用戶名
    uname = request.session.get('uname')
    # 獲取帖子的標(biāo)題
    title = request.POST.get('title')
    content = request.POST.get('content')
    return HttpResponse('%s發(fā)了一篇名為%s的帖子:%s' % (uname.encode('utf-8').decode('utf-8'),
                        title.encode('utf-8').decode('utf-8'),content.encode('utf-8').decode('utf-8')))

12,ajax登錄頁(yè)面布局代碼如下:

  • csrf_token 的目地是為了防止csrf公積,django默認(rèn)打開(kāi)csrf:如下代碼
  • 'django.middleware.csrf.CsrfViewMiddleware',
  • 查看網(wǎng)頁(yè)源代碼可知,csrf的鍵和值,所以請(qǐng)求的時(shí)候要攜帶,否則django直接禁止:
這里寫(xiě)圖片描述
  • ajax登錄頁(yè)面具體布局如下:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登錄頁(yè)面</title>
    <script src="/static/js/jquery-1.12.4.min.js"></script>
    <style>
        #errorMsg {
            display: none;
            color: red;
        }
    </style>
    <script>
        $(function () {

            $('#btnLogin').click(function () {
                $('uname').reset;

                csrf = $('input').val();
                uname = $('#uname').val();
                password = $('#password').val();
                vcode = $('#vcode').val();

                //發(fā)起ajax請(qǐng)求,注意csrf攻擊
                $.post('/login_ajax_check/', {
                    'csrfmiddlewaretoken': csrf,
                    'uname': uname,
                    'password': password,
                    'vcode': vcode,
                }, function (data) {
                    //獲取返回的數(shù)據(jù)并進(jìn)行操作
                    if (data.msg === 'ok') {
                        //登錄成功
                        location.href = '/success/' //跳轉(zhuǎn)到成功頁(yè)面
                    } else if (data.msg === 'fail_user') {
                        $('#errorMsg').show().text('親!用戶名或密碼錯(cuò)誤!')

                    } else if (data.msg === 'fail_verify') {
                        //驗(yàn)證碼錯(cuò)誤
                        $('#errorMsg').show().text('親!驗(yàn)證碼錯(cuò)誤!')
                    }
                })
            });
        });

    </script>
</head>

<body>

<div>
    {% csrf_token %}
    用戶名:<input type="text" id="uname"><br/>
    密  碼:<input type="password" id="password"><br/>

    驗(yàn)證碼:<input type="text" id="vcode"/><br/>
    <!--直接調(diào)用生產(chǎn)圖片驗(yàn)證碼的視圖函數(shù),生產(chǎn)驗(yàn)證碼-->
    ![](/verify_code/)<br/>

    <input type="button" value="登錄" id="btnLogin"><br/>
    <div id="errorMsg"></div>
</div>

</body>
</html>

13,登錄成功頁(yè)面,進(jìn)行發(fā)帖布局代碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登錄成功,發(fā)帖頁(yè)面</title>
</head>
<body>

<h2>親!你登錄成功了,歡迎你!?。?lt;/h2>
<form method="post" action="/post_article/">
    {% csrf_token %}
    標(biāo)題:<input type="text" name="title"/><br/>
    內(nèi)容:<textarea name="content"></textarea><br/>
    <input type="submit" value="發(fā)帖"/>
</form>
</body>
</html>

14,執(zhí)行遷移,生成session表

  • session表示需要執(zhí)行遷移后,才會(huì)在mysql數(shù)據(jù)庫(kù)中生成
這里寫(xiě)圖片描述

15,查看mysql數(shù)據(jù)庫(kù)

  • show tables;查看數(shù)據(jù)庫(kù)test04中的表
  • django_session就是session表
這里寫(xiě)圖片描述
這里寫(xiě)圖片描述
  • desc django_session;查看session表結(jié)構(gòu):
  • 有session的鍵、值和過(guò)期時(shí)間
這里寫(xiě)圖片描述

16,開(kāi)始登錄測(cè)試

  • 輸入用戶名、密碼和驗(yàn)證碼
這里寫(xiě)圖片描述
  • 這是登錄成功后的頁(yè)面,進(jìn)行發(fā)帖
這里寫(xiě)圖片描述
  • 這是發(fā)帖頁(yè)面
這里寫(xiě)圖片描述

17,查看數(shù)據(jù)庫(kù)中session表

這里寫(xiě)圖片描述

查看Cookie中的sessionid值為“hzlqkmdkn6461kfwfm2oj7p5889o2fo1”,數(shù)據(jù)表中session的鍵為“hzlqkmdkn6461kfwfm2oj7p5889o2fo1”,是一樣的,這樣,服務(wù)器就可以在眾多的請(qǐng)求者中找到對(duì)應(yīng)的Session數(shù)據(jù)。

這里寫(xiě)圖片描述

在MySQL數(shù)據(jù)庫(kù)命令行中復(fù)制值,在Base64解碼中進(jìn)行解碼查看如下圖。

這里寫(xiě)圖片描述

18,代碼github地址如下:

https://github.com/ITXIAOKE/pythonLoginProject

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容