一、用戶認(rèn)證系統(tǒng)
- Django內(nèi)置一個(gè)用戶認(rèn)證系統(tǒng),使用auth模塊實(shí)現(xiàn)。
- auth模塊提供了登錄、注冊(cè)、效驗(yàn)、修改密碼、注銷、驗(yàn)證用戶是否登錄等功能。
![]()
- Django默認(rèn)創(chuàng)建的數(shù)據(jù)庫表。
表名 | 作用 |
---|---|
auth_user | 用戶表 |
auth_user_groups | 用戶所屬組的表 |
auth_user_user_permissions | 用戶權(quán)限表 |
auth_group | 用戶組表 |
auth_group_permissions | 用戶組權(quán)限表 |
auth_permission | 存放全部權(quán)限的表,其他的表的權(quán)限都是從此表中外鍵連接過去的 |
django_session | 保存HTTP狀態(tài) |
django_migrations | 數(shù)據(jù)庫遷移記錄 |
二、案例:登陸認(rèn)證
2.1 平臺(tái)登入
1.登陸成功,進(jìn)入平臺(tái)首頁;登陸失敗,返回錯(cuò)誤信息。
###################################################
1、定義url路由規(guī)則,ORM/urls.py文件。
from django.contrib import admin
from django.urls import path,include,re_path
from ORM import views
urlpatterns = [
path('admin/', admin.site.urls),
re_path('^$',views.home),
path('myapp/',include('myapp.urls')),
path('login/',views.login)
]
###################################################
2、定義視圖,ORM/views.py文件。
from django.shortcuts import render,HttpResponse,redirect
from django.contrib import auth
def home(request):
return render(request,'index.html')
def login(request):
if request.method == "GET":
return render(request, 'login.html')
elif request.method == "POST":
username = request.POST.get('username')
password = request.POST.get('password')
user = auth.authenticate(username=username, password=password)
if user:
##驗(yàn)證通過后,將session信息保存到數(shù)據(jù)庫中。
auth.login(request, user)
return redirect("/")
else:
msg = "用戶名或密碼錯(cuò)誤!"
return render(request,'login.html',{'msg':msg})
###################################################
3、定義html模板,templates/login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>管理后臺(tái)頁面</title>
</head>
<body>
<ht>歡迎訪問管理后臺(tái)</ht>
<form action="" method="post">
用戶名 : <input type="text" name="username"><br>
密碼 : <input type="text" name="password"><br>
<button type="submit">登錄</button>
<span style="color: red">{{ msg }}</span>
</form>
</body>
</html>
###################################################
4、平臺(tái)首頁渲染模板templates/index.html,新增”退出登錄“按鈕。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>平臺(tái)首頁</title>
</head>
<body>
<h1>網(wǎng)站首頁</h1>
<a href="/logout"><button>退出登錄</button></a>
</body>
</html>
2.進(jìn)入django管理后臺(tái),新增一個(gè)測(cè)試用戶xiaoming,添加auth權(quán)限。
3.測(cè)試效果。
2.2 平臺(tái)登出
- 就是清空django_session表中記錄的用戶登錄狀態(tài)信息,若數(shù)據(jù)存在該表中,則認(rèn)定處于登陸狀態(tài);刪除數(shù)據(jù),則認(rèn)定登出。
1.退出登錄,返回到登陸頁面。
###################################################
1、定義url路由規(guī)則,ORM/urls.py文件。
from django.contrib import admin
from django.urls import path,include,re_path
from ORM import views
urlpatterns = [
path('admin/', admin.site.urls),
re_path('^$',views.home),
path('myapp/',include('myapp.urls')),
path('login/',views.login),
path('logout/',views.logout), ##新增url
]
###################################################
2、新增視圖,ORM/views.py文件。
def logout(request):
# 清除當(dāng)前用戶的session信息
auth.logout(request)
return redirect('/login')
2.3 login_required裝飾器
- login_required裝飾器:判斷用戶是否登錄,如果沒有登錄引導(dǎo)至登錄頁面,登錄成功后跳轉(zhuǎn)到目的頁面。
1.在settings.py文件設(shè)置沒有登錄默認(rèn)跳轉(zhuǎn)頁面。
##文件末尾添加。
LOGIN_URL = '/login/'
2.在需要登錄后才能訪問頁面的視圖添加裝飾器。
from django.contrib.auth.decorators import login_required
@login_required() ##語法糖引用裝飾器。
def user_add(request):
......
......
3.效果驗(yàn)證。
三、Django Session管理
Session與Cookie是什么?
- 網(wǎng)站采用是HTTP協(xié)議,它本身就是一個(gè)無狀態(tài)的,記不住我們上次來瀏覽器上做了什么事。
- 這時(shí),服務(wù)器給每個(gè)用戶貼了一個(gè)小紙條,上面記錄了服務(wù)器給我們返回的一些信息。后面服務(wù)器看到這張小紙條就知道我們是誰了。
- 這個(gè)小紙條就是Cookie。
Cookie工作原理:
- 瀏覽器第一次訪問服務(wù)器時(shí),服務(wù)器此時(shí)肯定不知道它的身份,所以創(chuàng)建一個(gè)獨(dú)特的身份標(biāo)識(shí)數(shù)據(jù),格式為key=value,放入到Set-Cookie字段里,隨著響應(yīng)報(bào)文發(fā)給瀏覽器。
- 瀏覽器看到有Set-Cookie字段以后就知道這是服務(wù)器給的身份標(biāo)識(shí),于是就保存起來,下次請(qǐng)求時(shí)會(huì)自動(dòng)將此key=value值放入到Cookie字段中發(fā)給服務(wù)器。
- 服務(wù)器收到請(qǐng)求報(bào)文后,發(fā)現(xiàn)Cookie字段中有值,就能根據(jù)此值識(shí)別用戶的身份然后提供個(gè)性化的服務(wù)。
![]()
Session的作用:
- 試想一下,如果將用戶賬戶的一些信息都存入Cookie中的話,一旦信息被攔截,那么所有的賬戶信息都會(huì)可能被泄露丟,這是不安全的。
- 所以就出現(xiàn)了Session,在一次會(huì)話中將重要信息保存在Session中,瀏覽器只記錄SessionId,一個(gè)SessionId對(duì)應(yīng)一次會(huì)話請(qǐng)求。
![]()
3.1 Django使用Session
3.1.1 Cookie用法
- 在settings.py配置文件中設(shè)置客戶端Cookie。
參數(shù) | 描述 |
---|---|
SESSION_COOKIE_NAME = “sessionid” | Session的cookie保存在瀏覽器上時(shí)的key 即:sessionid=隨機(jī)字符串(默認(rèn)) |
SESSION_COOKIE_PATH = “/” | Session的cookie保存的路徑(默認(rèn)) |
SESSION_COOKIE_DOMAIN = None | Session的cookie保存的域名(默認(rèn)) |
SESSION_COOKIE_SECURE = False | 是否Https傳輸cookie(默認(rèn)) |
SESSION_COOKIE_HTTPONLY = True | 是否Session的cookie只支持http傳輸(默認(rèn)) |
SESSION_COOKIE_AGE = 1209600 | Session的cookie失效日期(2周)(默認(rèn)) |
SESSION_EXPIRE_AT_BROWSER_CLOSE = False | 是否關(guān)閉瀏覽器使得Session過期(默認(rèn)) |
SESSION_SAVE_EVERY_REQUEST = False | 是否每次請(qǐng)求都保存Session,默認(rèn)修改之后才保存(默認(rèn)) |
1.設(shè)置Cookie過期時(shí)間,單位s。
##ORM/settings.py文件末尾添加此行。
SESSION_COOKIE_AGE = 30*60
2.設(shè)置關(guān)閉瀏覽器使得Session過期。
##ORM/settings.py文件末尾添加此行。
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
3.1.2 Session用法
- 在視圖中操作Session。
參數(shù) | 描述 |
---|---|
request.session[‘key’] = value | 向Session寫入鍵值 |
request.session.get(‘key’,None) | 獲取Session中鍵的值 |
request.session.flush() | 清除Session數(shù)據(jù) |
request.session.set_expiry(value) | Session過期時(shí)間 |
1.自定義向Session寫入鍵值,前端可以拿到該value值。
3.2 案例:用戶登錄認(rèn)證
1.自己實(shí)現(xiàn)登陸驗(yàn)證功能。
############################################################################
##根據(jù)上文內(nèi)容,將login接口試圖修改成如下內(nèi)容。
def login(request):
if request.method == "GET":
return render(request, 'login.html')
elif request.method == "POST":
username = request.POST.get('username')
password = request.POST.get('password')
if username =="qingjun" and password == "citms@123":
#登錄成功,is_login設(shè)置為True
request.session['is_login'] = True
request.session[ 'username'] = username #保存用戶名到數(shù)據(jù)庫。
return redirect("/")
else:
msg ="用戶名或密碼錯(cuò)誤 !"
return render(request,'login.html',{'msg': msg})
############################################################################
1、定義裝飾器,可以給其他視圖引用,新增文件ORM/main.py。
from django.shortcuts import render,HttpResponse,redirect
def self_login_required(func):
def inner(request):
is_login = request.session.get('is_login', False)
if is_login:
return func(request)
else:
return redirect("/login")
return inner
############################################################################
2、引用裝飾器。
from ORM.main import self_login_required
@self_login_required
def home(request):
return render(request, 'index.html')
2.查看效果。
四、Django CSRF安全防護(hù)機(jī)制
概念:
- CSRF(Cross Site Request Forgery):跨站請(qǐng)求偽造,實(shí)現(xiàn)的原理是CSRF攻擊者在用戶已經(jīng)登錄目標(biāo)網(wǎng)站之后,誘使用戶訪問一個(gè)攻擊頁面,利用目標(biāo)網(wǎng)站對(duì)用戶的信任,以用戶身份在攻擊頁面對(duì)目標(biāo)網(wǎng)站發(fā)起偽造用戶操作的請(qǐng)求,達(dá)到攻擊目的。
Django怎么驗(yàn)證一個(gè)請(qǐng)求是不是CSRF?
- Django處理客戶端請(qǐng)求時(shí),會(huì)生成一個(gè)隨機(jī)Token,放到Cookie里一起返回,然后需要前端每次POST請(qǐng)求時(shí)帶上這個(gè)Token,可以放到POST數(shù)據(jù)里鍵為csrfmiddlewaretoken,或者放到請(qǐng)求頭鍵為X-CSRFToken,Django從這兩個(gè)位置取,每次處理都會(huì)攔截驗(yàn)證,通過比對(duì)兩者是否一致來判斷這個(gè)請(qǐng)求是不是非法,非法就返回403狀態(tài)碼。
可以攜帶CSRF Token發(fā)送給服務(wù)端的方法:文章來源:http://www.zghlxwxcb.cn/news/detail-681257.html
- from表單添加{% csrf_token %}標(biāo)簽,表單會(huì)攜帶一同提交。
- 如果你是Ajax請(qǐng)求,需要把csrf token字符串(也是通過拿{% csrf_token %}標(biāo)簽產(chǎn)生的值)放到data里一起提交,并且鍵名為csrfmiddlewaretoken或者放到請(qǐng)求頭傳遞服務(wù)端。
- 指定取消某函數(shù)視圖CSRF防護(hù)。
1.Django默認(rèn)啟用CSRF保護(hù)機(jī)制,當(dāng)有post請(qǐng)求時(shí),就會(huì)被攔截。
2.此時(shí)可以給html模板中添加csrf標(biāo)簽,瀏覽器可以其值與表單一起提交給服務(wù)端。
3.還有其他兩種方式。文章來源地址http://www.zghlxwxcb.cn/news/detail-681257.html
##########################################################
方式2,不建議使用,建議在html模板中添加標(biāo)簽方式返回。
from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def index(request):
return render(request, 'index.html')
##########################################################
var csrf_token = $("[name='csrfmiddlewaretoken']").val();
var data = {'id': '123', 'csrfmiddlewaretoken': csrf_token};
$.ajax({
type: "POST",
url: "/api",
data: data,
dataType: 'json'
})
到了這里,關(guān)于Django基礎(chǔ)7——用戶認(rèn)證系統(tǒng)、Session管理、CSRF安全防護(hù)機(jī)制的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!