Django 2.0 學習(21):Django Session

Django Session

Session 與Cookie

1.簡介
1.Cookie不屬於http協議範圍,因爲http協議沒法保持狀態,但實際狀況,咱們又須要"保持狀態",所以Cookie就在這樣一個場景下誕生。Cookie的工做原理:由服務器產生內容,瀏覽器收到請求後保存在本地;當瀏覽器再次訪問時,瀏覽器會自動帶上Cookie,這樣服務器就能經過Cookie的內容來判斷這個是"誰"了;
2.Cookie雖然在必定程度上解決了"保持狀態"的需求,可是因爲Cookie自己最大支持4096字節,以及Cookie自己保存在客戶端,可能被攔截或竊取,所以就須要有一種新的東西,它能支持更多的字節,而且能保存在服務器,有較高的安全性,這就是Session;
然而問題來了,基於http協議的無狀態特徵,服務器根本就不知道訪問者是"誰",那麼上述的Cookie就起到橋接的做用。咱們能夠給每一個客戶端的Cookie分配一個惟一的ID,這樣用戶在訪問時,經過Cookie服務器就知道來的人是"誰"。而後咱們在根據不一樣的Cookie的ID,在服務器上保存一段時間的私密資料,如"帳號密碼"等。
3.總結而言:Cookie彌補了http無狀態的不足,讓服務器知道來的人是"誰",可是Cookie以文本形式保存在本地,自身存在較差的安全性;因此咱們就經過Cookie識別不一樣的用戶,對應的在Session裏面保存私密的信息以及超過4096字節的文本;
4.上述所說的Cookie和Session實際上是共通性的東西,不限於語言和框架。javascript

2.認證機制
用戶登陸時,在驗證了用戶名和密碼的正確性後跳轉到後逃的頁面。可是測試發現,若是繞過登錄頁面。直接輸入後臺的URL地址也能夠直接訪問,這個顯然是不合理的。其實咱們缺失的就是Cookie和Session配合的驗證。有了這個驗證過程,咱們就能夠實現和其餘網站同樣必須登錄後才能進入後臺頁面了。先介紹下這種認證機制,每當咱們使用瀏覽器訪問一個登錄頁面時,一旦咱們經過了認證。服務器端就會發送一組隨機惟一的字符串(假設是123abc)到瀏覽器端,這個被存儲在瀏覽器端的東西就叫Cookie。而服務器端也會本身存儲如下用戶當前的狀態,好比login=true,username=hello之類的用戶信息。可是這種存儲是以字典形式存儲的,字典的惟一key就是剛纔發給用戶惟一的Cookie值。那麼若是在服務器端查看Session信息的話,理論上就會看到以下的字典:css

{"123abc": {"login": true, "username": "hello"}}

由於每一個Cookie都是惟一的,因此咱們在電腦上換個瀏覽器在登錄贊成網站也須要再次驗證。那麼爲何說咱們只是理論上看到這樣子的字典呢?由於出於安全性的考慮,其實對於上面那個大字典不只key值時被加密的,value值在服務器端也同樣是被加密的。知道了原理,咱們下面就用代碼來實現。html

3.Cookie前端

def foo(request):
    print(request.COOKIES)
    
    obj = redirect("/path/")
    obj = HttpResponse("content")
    obj = render(request, "html")
    
    obj.set_cookies("key", "value", max_age=60, path="/path/")
    obj.set_signed_cookie("key", "value", max_age=60, path="/path", salt="eric")
    request.get_signed_cookie("key", salt="eric")
    return obj

4.Session
在templates目錄下建立兩個html文件,login.html表明登錄頁面,backend表明後臺頁面,其代碼以下:java

login.htmlpython

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>login</title>
    <link rel="stylesheet" href="http://830909.blog.51cto.com/static/plugins/bootstrap-3.3.5-dist/css/bootstrap.min.css">
</head>
<body>
    <div class="container">
        <form action="login.html" method="post">
            <div class="form-group">
                <label class="sr-only">username</label>
                <input type="text" class="form-control" name="username" placeholder="用戶名"/>
            </div>
            <div class="form-group">
                <label class="sr-only">Password</label>
                <input type="password" class="form-control" name="passwd" placeholder="密碼"/>
            </div>
            <div class="form-group">
                <input class="btn btn-primary" type="submit" value="http://830909.blog.51cto.com/8311014/Submit">
            </div>
        </form>
</div>
<script type="application/Javascript" src="http://830909.blog.51cto.com/static/js/jquery-2.2.1.min.js"></script>
<script type="application/javascript" src="http://830909.blog.51cto.com/static/plugins/bootstrap-3.3.5-dist/js/bootstrap.min.js"></script>
</body>
</html>

backend.htmljquery

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>backend</title>
    <link rel="stylesheet" href="http://830909.blog.51cto.com/static/plugins/bootstrap-3.3.5-dist/css/bootstrap.min.css">
    <link rel="stylesheet" href="http://830909.blog.51cto.com/static/css/commons.css">
</head>
<body>
<div class="container">
    <h2>cookie 內容是 {{ cookie_content }}</h2>
    <h2>session 內容是 {{ session_content }}</h2>
    <h2>登陸用戶名 :{{ username }}</h2>
    <a href="http://830909.blog.51cto.com/logout/">註銷</a>
</div>
<script type="application/javascript" src="http://830909.blog.51cto.com/static/js/jquery-2.2.1.min.js"></script>
<script type="application/javascript" src="http://830909.blog.51cto.com/static/plugins/bootstrap-3.3.5-dist/js/bootstrap.min.js"></script>
</body>
</html>

接下來編輯應用下的views.py文件,編寫代碼邏輯部分:數據庫

from django.shortcuts import redirect, render
def login(request):
    if request.method == "POST":
        username = request.POST["username"]
        passwd = redirect.POST["passwd"]
        if username == "abc" and passwd == "123":
            # 設置session內部的字典內容
            request.session["is_login"] = True
            request.session["username"] = "abc"
            # 登錄成功就將url重定向到後臺的url
            return redirect("/backend/")
        
        # 登錄不成功或第一次訪問就停留在登錄頁面
        return render(request, "login.html")
    
def backend(request):
    """
    這裏必須用讀取字典的get()方法把is_login的value缺省值設置爲False,當用戶訪問backend這個url先嚐試獲取這個瀏覽器對應session中的is_login的值。若是用戶登錄成功的話,在login裏面就已經把is_login的值修改成了True,繁殖這個值就是False
    """
    is_login = request.session.get("is_login", False)
    # 若是爲True,說明用戶是正常登錄
    if is_login:
        # 獲取字典的內容並傳入頁面文件
        cookie_content = request.COOKIES
        session_content = redirect.session
        username = request.session["username"]
        return render(request, "backend.html", 
            {"cookie_content": cookie_content,
             "session_content": session_content,
             "username": username})
    else:
        """
        若是訪問的時候沒有攜帶正確的session,就直接被重定向到login頁面
        """
        return redirect("/login/")

def logout(request):
    """
    直接經過request.session["is_login"]回去返回的時候,若是is_login對應的value值不存在會致使程序異常。因此須要作異常處理
    """
    try:
        # 刪除is_login對應的value值
        del request.session["is_login"]
    except KeyError:
        pass
    # 點擊註銷以後,直接重定向到登錄頁面
    return redirect("/login/")

編輯項目下的urls.py文件,設置函數與頁面的綁定關係,其代碼以下:django

from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', views.login),
    url(r'^backend/', views.backend),
    url(r'^logout/', views.logout),
]

最後打開瀏覽器直接訪問/backend/頁面的時候直接就被重定向到/login/頁面:
bootstrap

只有在輸入了正確的用戶名和密碼以後才進入到了/backend/頁面:

從上圖咱們能夠看出來:
1.login頁面正確登錄的話,後臺頁面能夠獲取到瀏覽器攜帶的Cookie;
2.第一行的sessionid其實就是Cookie的值;
3.session的內容是加密的,從客戶端獲取不到session的內容;
4.服務端能夠經過預設的key值去除session的內容並打印到前端;
在火狐瀏覽器中查看Cookie:

Django的session默認是存儲在數據庫裏的,,在數據庫中查看一下session內容:

5.Cookie和Session總結
Cookie:

# 一、獲取Cookie:
# request.COOKIES['key']
# request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)
#     參數:
#         default: 默認值
#            salt: 加密鹽
#         max_age: 後臺控制過時時間



# 二、設置Cookie:
# rep = HttpResponse(...) 或 rep = render(request, ...)
#
# rep.set_cookie(key,value,...)
# rep.set_signed_cookie(key,value,salt='加密鹽',...)
#     參數:
#         key,              鍵
#         value='',         值
#         max_age=None,     超時時間
#         expires=None,     超時時間(IE requires expires, so set it if hasn't been already.)
#         path='/',         Cookie生效的路徑,/ 表示根路徑,特殊的:跟路徑的cookie能夠被任何url的頁面訪問
#         domain=None,      Cookie生效的域名
#         secure=False,     https傳輸
#         httponly=False    只能http協議傳輸,沒法被JavaScript獲取(不是絕對,底層抓包能夠獲取到也能夠被覆蓋)



# 因爲cookie保存在客戶端的電腦上,因此,JavaScript和jquery也能夠操做cookie。

# <script src='/static/js/jquery.cookie.js'></script>
# $.cookie("list_pager_num", 30,{ path: '/' });

Session:

Django中默認支持Session,其內部提供了5種類型的Session供開發者使用:

  • 數據庫(默認)
  • 緩存
  • 文件
  • 數據庫+緩存
  • 加密

1.數據庫 Session

Django默認支持Session,而且默認是將Session數據存儲在數據庫中,即:django_session 表中。
 
a. 配置 settings.py
 
    SESSION_ENGINE = 'django.contrib.sessions.backends.db'   # 引擎(默認)
     
    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)
        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")
 
        ...

2.緩存 Session

a. 配置 settings.py
 
    SESSION_ENGINE = 'django.contrib.sessions.backends.cache'  # 引擎
    SESSION_CACHE_ALIAS = 'default'                            # 使用的緩存別名(默認內存緩存,也能夠是memcache),此處別名依賴緩存的設置
 
 
    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. 使用
 
    同上

3.文件 Session

a. 配置 settings.py
 
    SESSION_ENGINE = 'django.contrib.sessions.backends.file'    # 引擎
    SESSION_FILE_PATH = None                                    # 緩存文件路徑,若是爲None,則使用tempfile模塊獲取一個臨時地址tempfile.gettempdir()                                                            # 如:/var/folders/d3/j9tj0gz93dg06bmwxmhh6_xm0000gn/T
 
 
    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. 使用
 
    同上

4.數據庫+緩存 Session

數據庫用於作持久化,緩存用於提升效率
 
a. 配置 settings.py
 
    SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'        # 引擎
 
b. 使用
 
    同上

5.加密

a. 配置 settings.py
     
    SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'   # 引擎
 
b. 使用
 
    同上
相關文章
相關標籤/搜索