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)存中盯孙,文件類型為png
im.save(buf, 'png')
# 13鲁森,將內(nèi)存中的圖片數(shù)據(jù)返回給客戶端,MIME類型為圖片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)證碼-->
<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>親斩郎!你登錄成功了脑融,歡迎你!K跻恕肘迎!</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ě)圖片描述