1. 程式人生 > >Django Session Cookie使用

Django Session Cookie使用

一、cookie和session說明

由於http是無狀態的協議,不像tcp一樣可以保持連線,那麼這個時候使用者在通過http協議訪問時,伺服器並不知道具體是哪個使用者,導致無法根據某種狀態做一些特殊的處理,那麼這個時候,cookie就產生了

cookie就是伺服器基於不同的使用者或者使用者不同的狀態進行區分,進而執行不同的操作,如可以根據使用者cookie進行判定使用者是否登入,也可以通過web伺服器來根據不同的cookie定義做一些規則過

cookie雖然在一定程度上解決了“保持狀態”的需求,但是由於cookie本身最大支援4096位元組,以及cookie本身儲存在客戶端,可能被攔截或竊取,因此就需要有一種新的東西,它能支援更多的位元組,並且他儲存在伺服器,有較高的安全性。這就是session

問題來了,基於http協議的無狀態特徵,伺服器根本就不知道訪問者是“誰”。那麼上述的cookie就起到橋接的作用。

我們可以給每個客戶端的cookie分配一個唯一的id,這樣使用者在訪問時,通過cookie,伺服器就知道來的人是“誰”。然後我們再根據不同的cookie的id,在伺服器上儲存一段時間的私密資料,如“賬號密碼”等等。

總結而言:cookie彌補了http無狀態的不足,讓伺服器知道來的人是“誰”;但是cookie以文字的形式儲存在本地,自身安全性較差;所以我們就通過cookie識別不同的使用者,對應的在session裡儲存私密的資訊以及超過4096位元組的文字。

另外,上述所說的cookie和session其實是共通性的東西,不限於語言和框架


二、登入應用原理

當用戶通過使用者名稱和密碼進行登入,在驗證了使用者名稱和密碼的正確性後跳轉到後臺的頁面。但是測試後也發現,如果繞過登陸頁面。直接輸入後臺的url地址也可以直接訪問的。這個顯然是不合理的。其實我們缺失的就是cookie和session配合的驗證。有了這個驗證過程,我們就可以實現和其他網站一樣必須登入才能進入後臺頁面了。

先說一下這種認證的機制。每當我們使用一款瀏覽器訪問一個登陸頁面的時候,一旦我們通過了認證。伺服器端就會發送一組隨機唯一的字串(假設是123abc)到瀏覽器端,這個被儲存在瀏覽端的東西就叫cookie。而伺服器端也會自己儲存一下使用者當前的狀態,比如login=true,username=hahaha之類的使用者資訊。但是這種儲存是以字典形式儲存的,字典的唯一key就是剛才發給使用者的唯一的cookie值。那麼如果在伺服器端檢視session資訊的話,理論上就會看到如下樣子的字典

{‘123abc’:{‘login’:true,‘username:hahaha’}}

因為每個cookie都是唯一的,所以我們在電腦上換個瀏覽器再登陸同一個網站也需要再次驗證。那麼為什麼說我們只是理論上看到這樣子的字典呢?因為處於安全性的考慮,其實對於上面那個大字典不光key值123abc是被加密的,value值{‘login’:true,‘username:hahaha’}在伺服器端也是一樣被加密的。所以我們伺服器上就算開啟session資訊看到的也是類似與以下樣子的東西

{‘123abc’:dasdasdasd1231231da1231231}


三、Django 基於cookie和session的認證

def login(request):
    if request.method == 'GET':
        return render(request, 'login.html')
    elif request.method == 'POST':
        user = request.POST.get('user', None)
        password =request.POST.get('password', None)
        if user  == 'root' and password == '123':
            # 1、生成隨機字串, 該隨機字串作為cookie的value及session的key
            # 2、將生成的字串傳給使用者瀏覽器cookie
            # 3、定義session資訊, 定義session_key為隨機字串,session_data為base64加密的使用者資訊
            request.session['username'] = user
            request.session['is_login'] = True
            if request.POST.get('none_login', None):
                # 獲取使用者選中的登入時長並設定超時時間
                request.session.set_expiry(3600*24*30)
            return redirect('/page/index/')
        else:
            return render(request, 'login.html')

def index(request):
    if request.session.get('username', None):
        return render(request, 'index.html')
    else:
        return redirect('/page/login/')

四、session的方法

        # 增刪查改
        request.session['k1']                     # 獲取值,如果不存在可能會報錯
        request.session.get('k1', None)           # 獲取值,如果不存在也不會報錯
        request.session['k1'] = 123               # 設定值,如果存在則更新
        request.session.setdefault('k1', 123)     # 設定值,如果存在則不設定
        del request.session['k1']                 # 刪除值裡面的單條資訊

        # 所有鍵,值,鍵值對
        request.session.keys()
        request.session.values()
        request.session.items()
        
        # 使用者session的隨機字串
        request.session.session_key

        # 將所有session失效日期小於當前日期的資料刪除
        request.session.clear_expired()

        # 檢查使用者session的隨機字串,在資料庫中是否存在
        request.session.exists('session_key')

        # 先獲取當前使用者的session-id,然後進行刪除這個session, 使用者登出用
        request.session.clear()

        # 刪除當前使用者的所有session資料
        request.session.delete('session_key')

        request.session.set_expiry(value)
            * 如果value是個整數,session會在多少些秒後失效
            * 如果value是個datetime或timedelta,session就會在這個時間後失效
            * 如果value是0,使用者關閉瀏覽器session就會失效
            * 如果value是None,session會依賴全域性session失效策略

    PS: cookie中不設定超時時間,則表示關閉瀏覽器自動清除
        session過期時間預設為兩週(django)


五、session的一般配置

定義session的cookie儲存在瀏覽器端的名稱,預設為sessionid (預設)
SESSION_COOKIE_NAME = ‘sessionid’

設定session的cookie的失效日期(預設)
SESSION_COOKIE_AGE = 1209600

設定session的cookie的作用域(預設)
SESSION_COOKIE_DOMAIN = None

設定是否https傳輸cookie(預設)
SESSION_COOKIE_SECURE = False

設定session的cookie儲存的路徑(預設)
SESSION_COOKIE_PATH = ‘/’

設定是否session的cookie只支援http(預設)
SESSION_COOKIE_HTTPONLY = True

是否每次請求都儲存session(預設)(如果改引數為true,則每次請求的時候session過期時間會進行重置,並且使用者瀏覽器cookie過期時間也會重置)
SESSION_SAVE_EVERY_REQUEST = False

是否關閉瀏覽器都使得session(預設)
SESSION_EXPIRE_AT_BROWSER_CLOSE = False

定義session的儲存是否為file(預設)
SESSION_FILE_PATH = None

序列化session儲存資料(預設)
SESSION_SERIALIZER = ‘django.contrib.sessions.serializers.JSONSerializer’


六、session的引擎配置

session引擎型別

SESSION_ENGINE = 'django.contrib.sessions.backends.db'                    # 資料庫(預設)
SESSION_ENGINE = 'django.contrib.sessions.backends.file'                  # 檔案
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'                 # 快取
SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'             # 快取資料庫
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'        # 加密cookie

6.1 快取 session

SESSION_ENGINE = ‘django.contrib.sessions.backends.cache’ # 引擎
SESSION_CACHE_ALIAS = ‘default’ # cache使用default的配置,default位於CACHES中的default

例如: 將快取內容儲存至記憶體
CACHES = {
    'default1': {
        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
        'LOCATION': 'unique-snowflake',
    }
}
例如: 將快取內容儲存至memcache
CACHES = {
    'default2': {
        'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
        'LOCATION': [
            '172.19.26.240:11211',
            '172.19.26.242:11211',
        ]
    }
}
例如: 將快取內容儲存至redis(django預設不支援redis,需要安裝django-redis)
CACHES = {
    "default3": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/1",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
            "PASSWORD": "xxxxxxx",
        }
    }
}

6.2 檔案session

SESSION_ENGINE = ‘django.contrib.sessions.backends.file’ # 引擎
SESSION_FILE_PATH = None # 快取檔案路徑,如果為None,則使用tempfile模組獲取一個臨時地址tempfile
SESSION_FILE_PATH = os.path.join(BASE_DIR, ‘cache’)

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
        'LOCATION': '/var/tmp/django_cache',
    }
}

6.3 快取加資料庫

快取加資料庫session(先去快取裡面拿,如果沒有則去資料庫裡面拿)
SESSION_ENGINE = ‘django.contrib.sessions.backends.cached_db’ # 引擎


6.4 加密cookie session

SESSION_ENGINE = ‘django.contrib.sessions.backends.signed_cookies’ # 引擎