靜態文件
- 項目中的CSS、圖片、js都是靜態文件
- 備註:本文基於django版本1.11展開, 技術棧會有所升級, 僅供參考!
1 ) 配置靜態文件
-
在settings 文件中定義靜態內容
STATIC_URL = '/static/' STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'static'), ]
-
在項目根目錄下創建static目錄,再創建當前應用名稱的目錄
- mysite/static/myapp/
-
在模板中可以使用硬編碼
- /static/my_app/myexample.jpg
-
在模板中可以使用static編碼
{ % load static from staticfiles % } <img src="{ % static "app/myexample.jpg" % }" alt="My image"/>
Csrf
-
CSRF(Cross-site request forgery)跨站請求僞造,也被稱爲“One Click Attack”或者Session Riding,通常縮寫爲CSRF或者XSRF,是一種對網站的惡意利用。儘管聽起來像跨站腳本XSS,但它與XSS非常不同,XSS利用站點內的信任用戶,而CSRF則通過僞裝來自受信任用戶的請求來利用受信任的網站。與XSS攻擊相比,CSRF攻擊往往不大流行(因此對其進行防範的資源也相當稀少)和難以防範,所以被認爲比XSS更具危險性
-
CSRF中間件和模板標籤爲防止跨站點請求僞造提供了易用的保護。
-
當惡意網站包含鏈接,表單按鈕或某些旨在在您的網站上執行某些操作的JavaScript時,會使用在瀏覽器中訪問惡意網站的登錄用戶的憑據進行此類攻擊。
-
還介紹了一種相關攻擊類型,即“登錄CSRF”,攻擊網站欺騙用戶的瀏覽器,以便使用其他人的憑證登錄到網站。
1 ) csrf的使用
- 在django的模板中,提供了防止跨站攻擊的方法
- 在settings.py中啓用’django.middleware.csrf.CsrfViewMiddleware’中間件,此項在創建項目時,默認被啓用
- 在HTML的表單中添加標籤
<form> { % csrf_token % } ... </form>
2 ) 取消保護
- 如果某些視圖不需要保護,可以使用裝飾器csrf_exempt,模板中也不需要寫標籤,修改csrf2的視圖如下
from django.views.decorators.csrf import csrf_exempt @csrf_exempt def csrf2(request): uname=request.POST['uname'] return render(request,'booktest/csrf2.html',{'uname':uname}) 運行上面的兩個請求,發現都可以請求
3 ) 保護原理
- 加入標籤後,可以查看源代碼,發現多瞭如下代碼
<input type='hidden' name='csrfmiddlewaretoken' value='nGjAB3Md9ZSb4NmG1sXDolPmh3bR2g59' />
- 在瀏覽器的調試工具中,可以查看cookie信息
- 查看跨站的信息,並沒有cookie信息,即使加入上面的隱藏域代碼,發現又可以訪問了
- 結論:django的csrf不是完全的安全
- 當提交請求時,中間件
django.middleware.csrf.CsrfViewMiddleware
會對提交的cookie及隱藏域的內容進行驗證,如果失敗則返回403錯誤
4 ) Ajax CSRF 認證
- GET 請求不需要 CSRF 認證,POST 請求需要正確認證才能得到正確的返回結果。
- 如果使用Ajax調用的時候,就要麻煩一些。需要注意以下幾點:
- 在視圖中使用render (而不要使用 render_to_response)
- 使用 jQuery 的 ajax 或者 post 之前 加入這個 js 代碼
jQuery(document).ajaxSend(function(event, xhr, settings) { function getCookie(name) { var cookieValue = null; if (document.cookie && document.cookie != '') { var cookies = document.cookie.split(';'); for (var i = 0; i < cookies.length; i++) { var cookie = jQuery.trim(cookies[i]); // Does this cookie string begin with the name we want? if (cookie.substring(0, name.length + 1) == (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } function sameOrigin(url) { // url could be relative or scheme relative or absolute var host = document.location.host; // host + port var protocol = document.location.protocol; var sr_origin = '//' + host; var origin = protocol + sr_origin; // Allow absolute or scheme relative URLs to same origin return (url == origin || url.slice(0, origin.length + 1) == origin + '/') || (url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') || // or any other URL that isn't scheme relative or absolute i.e relative. !(/^(\/\/|http:|https:).*/.test(url)); } function safeMethod(method) { return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); } if (!safeMethod(settings.type) && sameOrigin(settings.url)) { xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken')); } });
- 或者 更爲優雅簡潔的代碼(不能寫在 .js 中,要直接寫在模板文件中):
$.ajaxSetup({ data: {csrfmiddlewaretoken: '{ { csrf_token } }' }, });
- 這樣之後,就可以像原來一樣的使用 jQuery.ajax() 和 jQuery.post()了
狀態保持
- HTTP協議是無狀態的:每次請求都是一次新的請求,不會記得之前通信的狀態
- 客戶端與服務器端的一次通信,就是一次會話
- 實現狀態保持的方式:在客戶端或服務器端存儲與會話有關的數據
- 存儲方式包括cookie、session,會話一般指session對象
- 使用cookie,所有數據存儲在客戶端,注意不要存儲敏感信息
- 推薦使用sesison方式,所有數據存儲在服務器端,在客戶端cookie中存儲session_id
- 狀態保持的目的是在一段時間內跟蹤請求者的狀態,可以實現跨頁面訪問當前請求者的數據
- 注意:不同的請求者之間不會共享這個數據,與請求者一一對應
1 ) 開啓session
- 使用django-admin startproject創建的項目默認啓用
- 禁用會話:刪除下面指定的兩個值,禁用會話將節省一些性能消耗
- Django 中session需要依賴數據庫,因此需要確認數據庫中是否存在 與session相關的 表
- 在settings.py文件中
- INSTALLED_APPS列表中添加:‘django.contrib.sessions’
- MIDDLEWARE_CLASSES列表中添加:‘django.contrib.sessions.middleware.SessionMiddleware’
2 ) 使用session
- 啓用會話後,每個HttpRequest對象將具有一個session屬性,它是一個類字典對象
- get(key, default=None):根據鍵獲取會話的值
- clear():清除所有會話
- flush():刪除當前的會話數據並刪除會話的Cookie
- del request.session[‘member_id’]:刪除會話
- 示例:
#session設置 request.session[key] = value #session獲取 request.session.get(key,default=Node) #session刪除 # 刪除單個key 不存在時報錯 del request.session['a'] #清除所有會話,但不會刪除數據 request.session.clear() #刪除當前的會話數據 request.session.flush()
中間件
- 中間件是一個輕量級、底層的插件系統,可以介入Django的請求和響應處理過程,修改Django的輸入或輸出
- 激活:添加到Django配置文件中的MIDDLEWARE_CLASSES元組中
- 使用中間件,可以干擾整個處理過程,每次請求中都會執行中間件的這個方法
1 ) 驗證用戶是否登陸示例
- 在應用中創建AdminLoginMiddleware.py文件
class AppMiddleware: def __init__(self, get_response): self.get_response = get_response print('middleware init!') def __call__(self, request): print('middleware call!') response = self.get_response(request) return response
2 ) 配置中間件
- 在settings.py文件中修改MIDDLEWARE_CLASSES選項
MIDDLEWARE = [ #自定義的中間件 'app.app_middleware.AppMiddleware' ]
使用Django中提供的密碼方案
- 該django.contrib.auth.hashers模塊提供了一組函數來創建和驗證散列密碼。您可以獨立於User模型使用它們。
# from django.contrib.auth.hashers import make_password, check_password # 對密碼進行加密操作 # upass = make_password(request.POST['password'], None, 'pbkdf2_sha256') # print(upass) # 這裏是加密後的密碼 # b = check_password('1234567','pbkdf2_sha256$36000$197nqXM6yxYv$Zxh/Vsns8qszkvUmY81BgrjCeLPXhCHLEilP6VO+Rnc=') # print(b) # False 備註:check_password的參數:第一個是加密前的數據, 第二個是加密後的數據 # python中的MD5加密 # 獲取密碼並md5 import hashlib from django.http import HttpResponse m = hashlib.md5() m.update(bytes(request.POST['password'], encoding="utf8")) str = m.hexdigest() return HttpResponse("123456的md5是:" + str)
相關代碼示例
- 城市聯動
- 文件上傳
- 分頁
- 富文本編輯器
- session狀態維持
- 中間件
- 密碼管理
- 示例詳見代碼倉庫