前言

session: sessioncookie的作用有點類似,都是為了儲存使用者相關的資訊。不同的是,cookie是儲存在本地瀏覽器,session是一個思路、一個概念、一個伺服器儲存授權資訊的解決方案,不同的伺服器,不同的框架,不同的語言有不同的實現。雖然實現不一樣,但是他們的目的都是伺服器為了方便儲存資料的。session的出現,是為了解決cookie儲存資料不安全的問題的。

cookie和session的使用

web開發發展至今,cookiesession的使用已經出現了一些非常成熟的方案。在如今的市場或者企業裡,一般有兩種儲存方式:

  • 儲存在服務端:通過cookie儲存一個sessionid,然後具體的資料則是儲存在session中。如果使用者已經登入,則伺服器會在cookie中儲存一個sessionid,下次再次請求的時候,會把該sessionid攜帶上來,伺服器根據sessionid在session庫中獲取使用者的session資料。就能知道該使用者到底是誰,以及之前儲存的一些狀態資訊。這種專業術語叫做server side session。Django把session資訊預設儲存到資料庫中,當然也可以儲存到其他地方,比如快取中,檔案系統中等。儲存在伺服器的資料會更加的安全,不容易被竊取。但儲存在伺服器也有一定的弊端,就是會佔用伺服器的資源,但現在伺服器已經發展至今,一些session資訊還是綽綽有餘的。
  • session資料加密,然後儲存在cookie中。這種專業術語叫做client side sessionflask框架預設採用的就是這種方式,但是也可以替換成其他形式。

django中應用session

1.啟用session

要應用session,必須開啟session中間層,在settings中:

MIDDLEWARE = [
# 啟用 Session 中間層
'django.contrib.sessions.middleware.SessionMiddleware',
]

2.session的5種儲存機制

預設情況下,session資料是儲存到資料庫中的。我們如何得知呢?可以從Django的預設配置中檢視到,Django的預設配置路徑是from django.conf import global_settings,我們可以開啟然後檢視到預設配置,程式碼如下:

# Session的cookie儲存在瀏覽器上時的key,即:sessionid=隨機字串(預設)
SESSION_COOKIE_NAME = 'sessionid'
# Session的cookie失效日期(2周)(預設)
SESSION_COOKIE_AGE = 60 * 60 * 24 * 7 * 2
# 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,預設修改之後才儲存(預設)
SESSION_SAVE_EVERY_REQUEST = False
# 是否關閉瀏覽器使得Session過期(預設)
SESSION_EXPIRE_AT_BROWSER_CLOSE = False
# 儲存session資料預設使用的模組
SESSION_ENGINE = 'django.contrib.sessions.backends.db'
# session資料的序列化類
SESSION_SERIALIZER = 'django.contrib.sessions.serializers.JSONSerializer'

這裡我們可以看到SESSION_ENGINE = 'django.contrib.sessions.backends.db'django預設使用的是儲存到資料庫中,這只是儲存機制中的其中一種,下面我們逐一介紹

1.資料庫方式

使用資料庫。預設就是這種方案。

# 資料庫方式(預設):
SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 資料庫型別的session引擎需要開啟此應用,啟用 sessions 應用
INSTALLED_APPS = [
'django.contrib.sessions',
]

2.快取

使用快取來儲存session。想要將資料儲存到快取中,前提是你必須要在settings.py中配置好CACHES,並且是需要使用Memcached,而不能使用純記憶體作為快取。

SESSION_ENGINE = 'django.contrib.sessions.backends.cache'

3.快取+資料庫

在儲存資料的時候,會將資料先存到快取中,再存到資料庫中。這樣就可以保證萬一快取系統出現問題,session資料也不會丟失。在獲取資料的時候,會先從快取中獲取,如果快取中沒有,那麼就會從資料庫中獲取。

SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'

4.檔案

使用檔案來儲存session

SESSION_ENGINE = 'django.contrib.sessions.backends.file' 

# 設定檔案位置, 預設是 tempfile.gettempdir(),
# linux下是:/tmp
# windows下是: C:\Users\51508\AppData\Local\Temp
SESSION_FILE_PATH = 'd:\session_dir'

5.加密cookie

基於cookie的session,所有資料都儲存在cookie中,一般情況下不建議使用這種方式

  1. cookie有長度限制,4096個位元組
  2. cookie不會因為服務端的登出而無效,那麼可能造成攻擊者使用已經登出的cookie模仿使用者繼續訪問網站
  3. SECRET_KEY這個配置項絕對不能洩露,否則會讓攻擊者可以遠端執行任意程式碼
  4. cookie過大,會影響使用者訪問速度
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'

3.操作session

  1. get:用來從session中獲取指定值。
  2. pop:從session中刪除一個值。
  3. keys:從session中獲取所有的鍵。
  4. items:從session中獲取所有的值。
  5. clear:清除當前這個使用者的session資料。
  6. flush:刪除session並且刪除在瀏覽器中儲存的session_id,一般在登出的時候用得比較多。
  7. set_expiry(value):設定過期時間。
  • 整形:代表秒數,表示多少秒後過期。
  • 0:代表只要瀏覽器關閉,session就會過期。
  • None:會使用全域性的session配置。在settings.py中可以設定SESSION_COOKIE_AGE來配置全域性的過期時間。預設是1209600秒,也就是2周的時間。
  1. clear_expired:清除過期的session。Django並不會清除過期的session,需要定期手動的清理,或者是在終端,使用命令列python manage.py clearsessions來清除過期的session

實戰案例

session其實本質也是基於cookie使用的,使用起來跟session差不多,先建立3個路由地址

urlpatterns = [
path('set_session/', views.set_session, name='set_session'),
path('get_session/', views.get_session, name='get_session'),
path('clear_session/', views.clear_session, name='clear_session')
]

然後編寫對應的檢視

def set_session(request):
"""設定session"""
request.session["username"] = "jkc"
return HttpResponse("session_view") def get_session(request):
"""獲取session"""
username = request.session.get("username")
return HttpResponse(f"session的值為{username}") def clear_session(request):
"""清除session"""
request.session.clear()
return HttpResponse("清除session成功")

接著我們在瀏覽器上先開啟F12,然後輸入url地址http://127.0.0.1:8000/session/set_session/,我們可以看到響應頭中有後臺返回的set-cookie裡面有個sessionid,這個sessionid就是前端傳給後臺,後臺經過一系列加密操作後返回給前端瀏覽器的key



因為我們django預設儲存session的機制是資料庫,所以資料庫中的django_session表中也會有同樣key的一條資料

接著我們在瀏覽器上訪問http://127.0.0.1:8000/session/get_session/,瀏覽器頁面上會返回session的值為jkc,說明我們的session的key是正確的,且沒有過期。

 

最後再訪問http://127.0.0.1:8000/session/clear_session/,瀏覽器頁面返回清除session成功,如何證明呢?我們可以再次訪問http://127.0.0.1:8000/session/get_session/,我們會發現這次返回的是session的值為None,值為None說明session已經被清空