前言
session: session
和cookie
的作用有點類似,都是為了儲存使用者相關的資訊。不同的是,cookie
是儲存在本地瀏覽器,session
是一個思路、一個概念、一個伺服器儲存授權資訊的解決方案,不同的伺服器,不同的框架,不同的語言有不同的實現。雖然實現不一樣,但是他們的目的都是伺服器為了方便儲存資料的。session
的出現,是為了解決cookie儲存資料不安全
的問題的。
cookie和session的使用
web開發發展至今,cookie
和session
的使用已經出現了一些非常成熟的方案。在如今的市場或者企業裡,一般有兩種儲存方式:
- 儲存在服務端:通過
cookie
儲存一個sessionid
,然後具體的資料則是儲存在session
中。如果使用者已經登入,則伺服器會在cookie
中儲存一個sessionid
,下次再次請求的時候,會把該sessionid
攜帶上來,伺服器根據sessionid
在session庫中獲取使用者的session資料。就能知道該使用者到底是誰,以及之前儲存的一些狀態資訊。這種專業術語叫做server side session。Django把session
資訊預設儲存到資料庫中,當然也可以儲存到其他地方,比如快取中,檔案系統中等。儲存在伺服器的資料會更加的安全,不容易被竊取。但儲存在伺服器也有一定的弊端,就是會佔用伺服器的資源,但現在伺服器已經發展至今,一些session
資訊還是綽綽有餘的。 - 將
session
資料加密,然後儲存在cookie
中。這種專業術語叫做client side session
。flask
框架預設採用的就是這種方式,但是也可以替換成其他形式。
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中,一般情況下不建議使用這種方式
- cookie有長度限制,4096個位元組
- cookie不會因為服務端的登出而無效,那麼可能造成攻擊者使用已經登出的cookie模仿使用者繼續訪問網站
- SECRET_KEY這個配置項絕對不能洩露,否則會讓攻擊者可以遠端執行任意程式碼
- cookie過大,會影響使用者訪問速度
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'
3.操作session
- get:用來從session中獲取指定值。
- pop:從session中刪除一個值。
- keys:從session中獲取所有的鍵。
- items:從session中獲取所有的值。
- clear:清除當前這個使用者的session資料。
- flush:刪除session並且刪除在瀏覽器中儲存的
session_id
,一般在登出的時候用得比較多。 - set_expiry(value):設定過期時間。
- 整形:代表秒數,表示多少秒後過期。
- 0:代表只要瀏覽器關閉,
session
就會過期。 - None:會使用全域性的session配置。在settings.py中可以設定
SESSION_COOKIE_AGE
來配置全域性的過期時間。預設是1209600
秒,也就是2周的時間。
- 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已經被清空