內容概要
- cookie與session簡介
- django操作cookie與session
- django中間件簡介
- 如何自定義中間件
- csrf跨站請求偽造(釣魚網站)
- csrf相關操作
cookie與session簡介
http協議
四大特性
1.基於請求響應
2.基於TCP\IP作用於應用層之上
3.無狀態
基於http協議通信的服務端無法保存客戶端狀態
縱使見她千百遍 我都當她如初見
4.無(短)連接
隨着互聯網的發展 很多網站都需要保存客戶端狀態 為了實現該需求
# cookie與session應運而生(最初的功能核心:保存用戶狀態)
cookie:服務端讓客戶端瀏覽器保存的數據(kv鍵值對)
session:服務端保存的關於用戶相關的數據(kv鍵值對)
'''session的工作需要依賴於cookie'''
# 目前只要是需要用戶登錄的網站 基本都需要使用cookie
客戶端瀏覽器也可以拒絕保存cookie
django操作cookie
# 視圖函數必須返回HttpResponse對象
from django.shortcuts import HttpResponse,render,redirect
return HttpResponse()
return render()
return redirect()
# 要想操作cookie必須先產生對象,之后利用對象內置方法操作
obj1 = HttpResponse()
return obj1
obj2 = render()
return obj2
obj3 = redirect()
return obj3
# 設置與獲取cookie
obj.set_cookie() # 讓瀏覽器保存cookie數據
request.COOKIES.get() # 獲取瀏覽器攜帶過來的cookie數據
obj.set_cookie(max_age\expires) # 以秒為基准
obj.delete_cookie()
# 獲取當前用戶想要訪問的地址
request.path_info # 僅獲取url的后綴名
request.get_full_path() # 獲取的全路徑,包含問號后面的參數部分
代碼練習
from django.shortcuts import render, HttpResponse, redirect
# Create your views here.
from functools import wraps
# 校驗登錄裝飾器
def login_auth(func):
@wraps(func) # 裝飾器修復技術
def inner(request, *args, **kwargs):
# 給參數賦值獲取訪問之前頁面的數據
target_url = request.path_info
# 先校驗用戶的cookie
cookie_data = request.COOKIES.get('name')
if cookie_data == 'meng':
res = func(request, *args, **kwargs)
return res
else:
# 加上target_url可以獲取登錄之前訪問的頁面
return redirect('/login/?target_url=%s' % target_url)
return inner
@login_auth
def home(request):
return HttpResponse('登錄頁面該展示的內容')
@login_auth
def index(request):
return HttpResponse('index頁面,登錄頁面該展示的內容')
@login_auth
def func(request):
return HttpResponse('func頁面,登錄頁面該展示的內容')
def login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
if username == 'meng' and password == '123':
# 先獲取用戶登錄之前需要訪問的頁面,如果沒有數據跳轉到首頁
target_url = request.GET.get('target_url', '/home/') # 如果前面沒有數據,使用后面的數據
obj = redirect(target_url)
# 設置cookie
obj.set_cookie('name', 'meng',expires=3) # expires:設置幾秒丟掉cookie
# 跳轉到首頁
return obj
return render(request, 'login.html')
# 退出
def logout(request):
obj = redirect('/home/')
obj.delete_cookie('name')
return obj
django操作session
request.session[key] = value # 設置session
1.django自動產生一個隨機字符串
2.默認在django_session表中保存隨機字符串與數據的對應關系
3.將隨機字符串發送給客戶端瀏覽器保存
sessionid:隨機字符串
request.session.get(key) # 獲取session
1.django自動獲取瀏覽器發送過來的cookie數據 獲取隨機字符串
2.拿着隨機字符串去django_session表中比對
3.如果對應上了則獲取數據並解密成明文的形式
'''
需要記住的:
1.django默認的session失效時間>>>:兩周(14天)
2.同一個計算機上一個瀏覽器只會有一條數據生效,當session過期的時候可能會出現多條
還有可能是不同瀏覽器訪問,也可能出現多條數據。
'''
# 刪除當前會話的所有Session數據
request.session.delete() # 只刪除瀏覽器數據,客戶端不會刪除
# 刪除當前的會話數據並刪除會話的Cookie。
request.session.flush() # 推薦使用
這用於確保前面的會話數據不可以再次被用戶的瀏覽器訪問
# 設置會話Session和Cookie的超時時間
request.session.set_expiry(value)
* 如果value是個整數,session會在些秒數后失效。
* 如果value是個datatime或timedelta,session就會在這個時間后失效。
* 如果value是0,用戶關閉瀏覽器session就會失效。
* 如果value是None,session會依賴全局session失效策略。
# session的存儲位置是可以自定義的
1. 數據庫Session
SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 引擎(默認)
2. 緩存Session
SESSION_ENGINE = 'django.contrib.sessions.backends.cache' # 引擎
SESSION_CACHE_ALIAS = 'default' # 使用的緩存別名(默認內存緩存,也可以是memcache),此處別名依賴緩存的設置
3. 文件Session
SESSION_ENGINE = 'django.contrib.sessions.backends.file' # 引擎
SESSION_FILE_PATH = None # 緩存文件路徑,如果為None,則使用tempfile模塊獲取一個臨時地址tempfile.gettempdir()
4. 緩存+數據庫
SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db' # 引擎
5. 加密Cookie Session
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies' # 引擎
session流程解析

django中間件
django中間件類似於django的門戶 請求來和走都必須經過它
'''
當我們需要給web后端添加一些全局相關的功能時可以使用中間件
1.校驗每個用戶的訪問頻率
2.校驗每個用戶的登錄狀態
3.用戶黑名單、白名單
4.用戶權限
...
'''
django默認有七個中間件 並且還支持用戶自定義中間件
自定義中間件我們可以編寫五個方法
必須掌握的方法
# process_request(self,request)
1.當請求來的時候會從上往下依次執行每一個中間件里面的該方法
如果沒有則直接下一個
2.當該方法返回了HttpResponse對象 那么請求不再繼續往后執行
而是直接原路返回
# process_response(self,request,response)
1.當響應返回的時候會從下往上依次執行每一個中間件里面的該方法
如果沒有則直接下一個 該方法默認要返回response
2.該方法返回什么瀏覽器就會接收到什么(也就意味着我們可以中途攔截待返回的數據做其他處理)
# process_request方法如果直接返回HttpResonse對象則直接執行process_response原理返回
需要了解的方法
process_view
路由匹配成功之后執行視圖函數之前自動觸發
process_template_response
當返回的對象中含有render屬性自動觸發
process_exception
當視圖函數報錯之后會自動觸發
中間件簡介
什么是中間件?
官方的說法:中間件是一個用來處理Django的請求和響應的框架級別的鈎子。它是一個輕量、低級別的插件系統,用於在全局范圍內改變Django的輸入和輸出。每個中間件組件都負責做一些特定的功能。
但是由於其影響的是全局,所以需要謹慎使用,使用不當會影響性能。
說的直白一點中間件是幫助我們在視圖函數執行之前和執行之后都可以做一些額外的操作,它本質上就是一個自定義類,類中定義了幾個方法,Django框架會在請求的特定的時間去執行這些方法。
我們一直都在使用中間件,只是沒有注意到而已,打開Django項目的Settings.py文件,看到下圖的MIDDLEWARE配置項。
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
自定義中間件
中間件可以定義五個方法,分別是:(主要的是process_request和process_response)
必須掌握的方法:
process_request(self,request)
process_response(self, request, response)
需要了解的方法:
process_view(self, request, view_func, view_args, view_kwargs)
process_template_response(self,request,response)
process_exception(self, request, exception)
以上方法的返回值可以是None或一個HttpResponse對象,如果是None,則繼續按照django定義的規則向后繼續執行,如果是HttpResponse對象,則直接將該對象返回給用戶。
自定義一個中間件實例


process_request
# 我們來看看多個中間件時,Django是如何執行其中的process_request方法的。
# 自定義mymiddleware.py
from django.utils.deprecation import MiddlewareMixin
class MyMdd1(MiddlewareMixin):
def process_request(self, request):
print('我是mdd1的request方法')
class MyMdd2(MiddlewareMixin):
def process_request(self, request):
print('我是mdd2的request方法')
# views.py
def ab_md(request):
print('我是視圖函數ab_md')
return HttpResponse('ab_md')
# settions.py
MIDDLEWARE = [
'app01.mymiddleware.MyMdd1', # 自定義中間件mdd1
'app01.mymiddleware.MyMdd2' # 自定義中間件mdd2
]
后端打印:
我是mdd1的request方法
我是mdd2的request方法
我是視圖函數ab_md
# 總結:
1.中間件的process_request方法是在執行視圖函數之前執行的
2.當配置多個中間件時,會按照MIDDLEWARE中的注冊順序,也就是列表的索引值,從前到后的一次執行。
3.不同中間件之間傳遞的request都是同一個對象
4.當該方法返回了HttpResponse對象,那么請求不再繼續往后執行,而是直接原路返回
process_response
# 自定義mymiddleware.py
class MyMdd1(MiddlewareMixin):
def process_request(self, request):
print('我是mdd1的request方法')
def process_response(self, request,response):
print('我是mdd1的response方法')
return response
class MyMdd2(MiddlewareMixin):
def process_request(self, request):
print('我是mdd2的request方法')
def process_response(self, request,response):
print('我是mdd2的response方法')
return response
# 其余和上述代碼一致
后端打印:
我是mdd1的request方法
我是mdd2的request方法
我是視圖函數ab_md
我是mdd2的response方法
我是mdd1的response方法
# 總結:
1.當響應返回的時候會從下往上依次執行每一個中間 件里面的該方法,如果沒有則直接下一個 該方法默認要返回response
2.該方法返回什么瀏覽器就會接收到什么(也就意味着我們可以中途攔截待返回的數據做其他處理) # 原理和擊鼓傳花一樣,一個傳一個
3.當中間件返回了HttpResponse對象,那么請求不再繼續往后執行,而是直接原路返回
# process_request方法如果直接返回HttpResonse對象則直接執行process_response原路返回