xss,csrf,cookie,session
XSS攻擊
跨站指令碼攻擊
Django自動遮蔽跨站指令碼攻擊
如果要跳過限制有兩種方法
- 在後端遮蔽
from django.utils.safestring import marksafe
temp = "<a href='http://www.baidu.com'>百度</a>"
newtemp = marksafe(temp)
return render(request, 'hello.html', {'temp': newtemp})
在hello.html中a標籤就是可以連結百度的a標籤,如果不使用marksafe,在hello.html中temp返回的只是字串。
- 在前端遮蔽
上述程式碼中返回{‘temp’: temp},前端是無法得到可以連線的a標籤的,得到是字串,如果要得到可以執行的a標籤,可以使用safe關鍵字遮蔽對於xss的限制,使用方法為{{ temp | safe }}
CSRF
概念
CSRF是Cross Site Request Forgery的縮寫,即跨站請求偽造。
攻擊者盜用的一個人的身份,以這個人的名義傳送惡意請求,對於伺服器端來說是完全合法的,但是實現了攻擊者想要完成的操作,比如說盜號、新增系統管理員、轉賬等等。
CSRF攻擊過程
A網站是一個存在CSRF漏洞的網站,B網站為惡意網站,使用者user是A網站的合法使用者
- 使用者user輸入賬號密碼登入A網站
- 使用者驗證通過,A網站生成Cookie返回user的瀏覽器
- 使用者未退出A網站,在同一個瀏覽器中開啟B網站
- B網站接收請求,返回攻擊程式碼,併發送訪問A網站的請求
- 瀏覽器會根據B網站的請求,在使用者不之情的情況下,攜帶當前使用者的Cookie資訊,向A網站傳送請求。網站A檢測到的Cookie資訊是使用者user瀏覽器中的Cookie,因此認定是合法請求,所以會執行B的請求。
Django中通過CSRF驗證
CSRF驗證一般用於POST請求,在form表單中可以使用{% csrf_token %}
,對於ajax中的post請求可以使用如下方法
$.ajax({
url:'/blog/',
type:'POST',
data:{'csrfmiddlewaretoken':'{{ csrf_token }}'},
traditional:true,
success:function(arg){
}
})
這樣的方法是用了{{ csrf_token }獲取csrf值,即使用了模板語言,還可以使用另外一種方式方式獲取csrf值
var csrf = $('input[name="csrfmiddlewaretoken"]').val();
除此之外還可以使用另外一種方法,借用jquery.cookie.js,將cookie中csrf的token在放在請求頭中傳送到服務端,使用方法如下所示。
var token = $.cookie('csrftoken');
var user = $('#user').val();
$.ajax({
url: '/blog/',
type: 'POST',
headers: {'X-CSRFToken': token},
data: {'user': user}
success: function(arg){
}
})
cookie和session
http協議是無狀態歇息,一旦資料互動完畢,客戶端與服務端的連線就會關閉,再次互動資料就需要重新建立連線,但重新建立的連線是無法跟蹤上次的會話了。
例如a向購物車添加了一件產品,操作結束連結等待一段時間就會斷開,過一段時間後想要結賬,但不知道結賬是要為誰結賬。
cookie和session就是用來解決這個問題的。
cookie和session都是用來跟蹤使用者的整個會話的,不同的是cookie通過在客戶端記錄資訊確定使用者身份,session在服務端記錄資訊確定使用者身份。
cookie
cookie就是一小段文字資訊,當客戶端訪問服務端,服務端生成一個cookie通過response返回給客戶端。下次客戶端攜帶cookie訪問服務端,服務端就會依據此確定使用者狀態。
cookie是不可跨域的
Cookie在客戶端是由瀏覽器管理的,瀏覽器能夠保證A網站只會操作A網站的Cookie而不會操作B網站的Cookie 。瀏覽器判斷一個網站能否操作另一個網站的Cookie是依據域名,域名不一樣就無法操作。
cookie是可以記錄訪問次數的
cookie可以儲存賬號密碼
使用cookie實現使用者登入驗證
Django中獲取cookie
request.COOKIES.get('ticket')
Django中設定cookie
obj = redirect('/blog/')
obj.set_cookie('ticket', 'asdfasgasfgsadfasdffgadfas')
設定cookie超時時間
obj.set_cookie('ticket', 'asdfasgasfgsadfasdffgadfas', max_age=10) # 10秒後失效
設定cookie只在某一個URL中生效
obj.set_cookie('ticket', 'asdfasgasfgsadfasdffgadfas', path='/blog') # 只在向/blog發出請求時可以獲取到cookie,預設使用“/”預設所有URL都可以獲取
簽名cookie
設定
obj.set_signed_cookie('ticket', 'asdfasgasfgsadfasdffgadfas', salt='kkkk')
獲取
request.get_signed_cookie('ticket', salt='kkkk')
自定義簽名加密規則
在settings.py中SIGNING_BACKEND = “foo”,foo為自定義的加密解密方法
session
session是伺服器端記錄客戶狀態的機制,相比於cookie使用簡單,但增加了伺服器儲存負擔。
session生命週期
session在使用者第一次訪問伺服器的時候建立,session生成後,只要使用者繼續訪問,伺服器就會更新session的最後訪問時間,並維護該session。使用者每訪問伺服器一次,無論是否重寫session,伺服器都認為該使用者的session活躍了一次。
session有效期
為了防止記憶體溢位,需要清除長時間沒有活躍的session,該時間就是session的超時時間,超過超時時間session就會自動失效。
Django中的session
reqeust.session['username'] = 'Jack' # 儲存session
request.session.get('username') # 讀取session
Django中session引數的設定
session的儲存介質有五種
- 資料庫(預設)
- 快取
- 檔案
- 快取+資料庫
- 加密cookie
Django預設支援Session,並且預設是將Session資料儲存在資料庫中,即:django_session 表中。
a. 配置 settings.py
#不同的SESSION_ENGINE對應不同的儲存介質,使用時根據具體場景選擇一種
# 資料庫
SESSION_ENGINE = 'django.contrib.session.backends.db' # 預設
# 快取
SESSION_ENGINE = 'django.contrib.sessions.backends.cache' # 引擎
SESSION_CACHE_ALIAS = 'default' # 使用的快取別名(預設記憶體快取,也可以是memcache),此處別名依賴快取的設定
# 檔案
SESSION_ENGINE = 'django.contrib.sessions.backends.file'
SESSION_FILE_PATH = None # 快取檔案路徑,如果為None,則使用tempfile模組獲取一個臨時地址tempfile.gettempdir()
# 快取+資料庫
SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'
# 加密cookie
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'
# 以下設定適用於任何一種儲存介質
SESSION_COOKIE_NAME = "sessionid" # Session的cookie儲存在瀏覽器上時的key,即:sessionid=隨機字串(預設)
SESSION_COOKIE_PATH = "/" # Session的cookie儲存的路徑(預設)
SESSION_COOKIE_DOMAIN = None # Session的cookie儲存的域名(預設)
SESSION_COOKIE_SECURE = False # 是否Https傳輸cookie(預設)
SESSION_COOKIE_HTTPONLY = True # 是否Session的cookie只支援http傳輸(預設
SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周)(預設)
SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否關閉瀏覽器使得Session過期(預設)
SESSION_SAVE_EVERY_REQUEST = False # 是否每次請求都儲存Session,預設修改之後才儲存(預設)
b. 使用
def index(request):
# 獲取、設定、刪除Session中資料
request.session['k1'] # 獲取, 如果不存在會報錯
request.session.get('k1',None) # 獲取, 如果不存在返回None, 不會報錯
request.session['k1'] = 123 # 設定
request.session.setdefault('k1',123) # 存在則不設定
del request.session['k1']
# 所有 鍵、值、鍵值對
request.session.keys()
request.session.values()
request.session.items()
request.session.iterkeys()
request.session.itervalues()
request.session.iteritems()
# 使用者session的隨機字串
request.session.session_key
# 將所有Session失效日期小於當前日期的資料刪除
request.session.clear_expired()
# 檢查 使用者session的隨機字串 在資料庫中是否
request.session.exists("session_key")
# 刪除當前使用者的所有Session資料
request.session.delete("session_key")
request.session.set_expiry(value)
# 如果value是個整數,session會在些秒數後失效。
# 如果value是個datatime或timedelta,session就會在這個時間後失效。
# 如果value是0,使用者關閉瀏覽器session就會失效。
# 如果value是None,session會依賴全域性session失效策略。