1. 程式人生 > >xss,csrf,cookie,session

xss,csrf,cookie,session

XSS攻擊

跨站指令碼攻擊

Django自動遮蔽跨站指令碼攻擊

如果要跳過限制有兩種方法

  1. 在後端遮蔽
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返回的只是字串。

  1. 在前端遮蔽

上述程式碼中返回{‘temp’: temp},前端是無法得到可以連線的a標籤的,得到是字串,如果要得到可以執行的a標籤,可以使用safe關鍵字遮蔽對於xss的限制,使用方法為{{ temp | safe }}

CSRF

概念

CSRF是Cross Site Request Forgery的縮寫,即跨站請求偽造。

攻擊者盜用的一個人的身份,以這個人的名義傳送惡意請求,對於伺服器端來說是完全合法的,但是實現了攻擊者想要完成的操作,比如說盜號、新增系統管理員、轉賬等等。

CSRF攻擊過程

A網站是一個存在CSRF漏洞的網站,B網站為惡意網站,使用者user是A網站的合法使用者

  1. 使用者user輸入賬號密碼登入A網站
  2. 使用者驗證通過,A網站生成Cookie返回user的瀏覽器
  3. 使用者未退出A網站,在同一個瀏覽器中開啟B網站
  4. B網站接收請求,返回攻擊程式碼,併發送訪問A網站的請求
  5. 瀏覽器會根據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通過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失效策略。