1. 程式人生 > >Django中的session和cookie

Django中的session和cookie

檢查 刪除用戶 abi 不可 cti 包含 expired 傳輸 requires

session和cookie

技術分享圖片
一. 概念理解
你可能有留意到當你瀏覽網頁時,會有一些推送消息,大多數是你最近留意過的同類東西,比如你想買桌子,上淘寶搜了一下,結果連著幾天會有各種各樣的桌子的鏈接。這是因為
你瀏覽某個網頁的時候,WEB 服務器會先送一些資料放在你的計算機上,類似於你打的文字,選的一些東西什麽的,Cookie 會幫你都紀錄下來。當下次你再光臨同一個網站,WEB
服務器會先看看有沒有它上次留下的 Cookie 資料,有的話,就會依據 Cookie裏的內容來判斷使用者,送出特定的網頁內容給你。 Cookie 的使用很普遍,許多有提供個人化服務的
網站,都是利用 Cookie來辨認使用者,以方便送出使用者量身定做的內容。
然而,cookie是什麽呢?session又是什麽?
先來了解幾個概念。
  
1、無狀態的HTTP協議: 協議是指計算機通信網絡中兩臺計算機之間進行通信所必須共同遵守的規定或規則,超文本傳輸協議(HTTP)是一種通信協議,它允許將超文本標記語言(HTML)文檔從Web服務器 傳送到客戶端的瀏覽器。 HTTP協議是無狀態的協議。一旦數據交換完畢,客戶端與服務器端的連接就會關閉,再次交換數據需要建立新的連接。這就意味著服務器無法從連接上跟蹤會話。 2、會話(Session)跟蹤:   會話,指用戶登錄網站後的一系列動作,比如瀏覽商品添加到購物車並購買。會話(Session)跟蹤是Web程序中常用的技術,用來跟蹤用戶的整個會話。常用的會話跟蹤技術 是Cookie與Session。Cookie通過在客戶端記錄信息確定用戶身份,Session通過在服務器端記錄信息確定用戶身份。 二. Cookie 由於HTTP是一種無狀態的協議,服務器單從網絡連接上無從知道客戶身份。用戶A購買了一件商品放入購物車內,當再次購買商品時服務器已經無法判斷該購買行為是屬於用戶A的 會話還是用戶B的會話了。怎麽辦呢?就給客戶端們頒發一個通行證吧,每人一個,無論誰訪問都必須攜帶自己通行證。這樣服務器就能從通行證上確認客戶身份了。這就是Cookie 的工作原理。 Cookie實際上是一小段的文本信息。客戶端請求服務器,如果服務器需要記錄該用戶狀態,就使用response向客戶端瀏覽器頒發一個Cookie。客戶端會把Cookie保存起來。 當瀏覽器再請求該網站時,瀏覽器把請求的網址連同該Cookie一同提交給服務器。服務器檢查該Cookie,以此來辨認用戶狀態。服務器還可以根據需要修改Cookie的內容。
1、cookie的內容主要包括:名字,值,過期時間,路徑和域。路徑與域一起構成cookie的作用範圍。 1)Name 和 Value 屬性由程序設定,默認值都是空引用。 2)Domain屬性的默認值為當前URL的域名部分,不管發出這個cookie的頁面在哪個目錄下的。 3)Path屬性的默認值是根目錄,即 ”/” ,不管發出這個cookie的頁面在哪個目錄下的。可以由程序設置為一定的路徑來進一步限制此cookie的作用範圍。 4)Expires 屬性,這個屬性設置此Cookie 的過期日期和時間。 1 HttpCookie cookie = new HttpCookie("MyCook");//初使化並設置Cookie的名稱 2 DateTime dt = DateTime.Now; 3 TimeSpan ts = new TimeSpan(0, 0, 1, 0, 0);//過期時間為1分鐘 4 cookie.Expires = dt.Add(ts);//設置過期時間 5 cookie.Values.Add("
userid", "value"); 6 cookie.Values.Add("userid2", "value2"); 7 Response.AppendCookie(cookie); 2、Path和Domain屬性 --path:   如果http://www.china.com/test/index.html 建立了一個cookie,那麽在http://www.china.com/test/目錄裏的所有頁面,以及該目錄下面任何子目錄裏 的頁面都可以訪問這個cookie。這就是說,在http://www.china.com/test/test2/test3 裏的任何頁面都可以訪問http://www.china.com/test/index.html 建立的cookie。但是,如果http://www.china.com/test/ 需要訪問http://www.china.com/test/index.html設置的cookes,該怎麽辦? 這時,我們要把cookies的path屬性設置成“/”。在指定路徑的時候,凡是來自同一服務器,URL裏有相同路徑的所有WEB頁面都可以共享cookies。 --Domain: 比如: http://www.baidu.com/xxx/login.aspx 頁面中發出一個cookie,Domain屬性缺省就是www.baidu.com ,可以由程序設置此屬性為需要的值。   值是域名,比如www.china.com。這是對path路徑屬性的一個延伸。如果我們想讓 www.china.com能夠訪問bbs.china.com設置的cookies,該怎麽辦? 我們可以把 domain屬性設置成“china.com”, 並把path屬性設置成“/”。 3、會話Cookie和持久Cookie 若不設置過期時間,則表示這個cookie的生命期為瀏覽器會話期間,關閉瀏覽器窗口,cookie就消失。這種生命期為瀏覽器會話期的cookie被稱為會話cookie。會話cookie一般不存儲在 硬盤上而是保存在內存裏,當然這種行為並不是規範規定的。 若設置了過期時間,瀏覽器就會把cookie保存到硬盤上,關閉後再次打開瀏覽器,這些cookie仍然有效直到超過設定的過期時間。存儲在硬盤上的cookie可以在瀏覽器的不同進程間共享。 這種稱為持久Cookie。 4、Cookie具有不可跨域名性 就是說,瀏覽器訪問百度不會帶上谷歌的cookie。 三. Session Session是另一種記錄客戶狀態的機制,不同的是Cookie保存在客戶端瀏覽器中,而Session保存在服務器上。客戶端瀏覽器訪問服務器的時候,服務器把客戶端信息以某種形式記錄 在服務器上。這就是Session。客戶端瀏覽器再次訪問時只需要從該Session中查找該客戶的狀態就可以了。 每個用戶訪問服務器都會建立一個session,那服務器是怎麽標識用戶的唯一身份呢?事實上,用戶與服務器建立連接的同時,服務器會自動為其分配一個SessionId。 1、兩個問題: 1)什麽東西可以讓你每次請求都把SessionId自動帶到服務器呢?顯然就是cookie了,如果你想為用戶建立一次會話,可以在用戶授權成功時給他一個唯一的cookie。當一個 用戶提交了表單時,瀏覽器會將用戶的SessionId自動附加在HTTP頭信息中,(這是瀏覽器的自動功能,用戶不會察覺到),當服務器處理完這個表單後,將結果返回給SessionId 所對應的用戶。試想,如果沒有 SessionId,當有兩個用戶同時進行註冊時,服務器怎樣才能知道到底是哪個用戶提交了哪個表單呢。 2)儲存需要的信息。服務器通過SessionId作為key,讀寫到對應的value,這就達到了保持會話信息的目的。 2、session的創建: 當程序需要為某個客戶端的請求創建一個session時,服務器首先檢查這個客戶端的請求裏是否已包含了sessionId,如果已包含則說明以前已經為此客戶端創建過session,服務 器就按照sessionId把這個session檢索出來使用(檢索不到,會新建一個),如果客戶端請求不包含sessionId,則為此客戶端創建一個session並且生成一個與此session相關 聯的sessionId,sessionId的值是一個既不會重復,又不容易被找到規律以仿造的字符串,這個sessionId將被在本次響應中返回給客戶端保存。 3、禁用cookie:   如果客戶端禁用了cookie,通常有兩種方法實現session而不依賴cookie。 1)URL重寫,就是把sessionId直接附加在URL路徑的後面。 2)表單隱藏字段。就是服務器會自動修改表單,添加一個隱藏字段,以便在表單提交時能夠把session id傳遞回服務器。比如: <form name="testform" action="/xxx"> <input type="hidden" name="jsessionid" value="ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764"> <input type="text"> </form> 4、Session共享: 對於多網站(同一父域不同子域)單服務器,我們需要解決的就是來自不同網站之間SessionId的共享。由於域名不同(aaa.test.com和bbb.test.com),而SessionId又分別儲存 在各自的cookie中,因此服務器會認為對於兩個子站的訪問,是來自不同的會話。解決的方法是通過修改cookies的域名為父域名達到cookie共享的目的,從而實現SessionId的共 享。帶來的弊端就是,子站間的cookie信息也同時被共享了。 四. 總結 1、cookie數據存放在客戶的瀏覽器上,session數據放在服務器上。 2、cookie不是很安全,別人可以分析存放在本地的cookie並進行cookie欺騙,考慮到安全應當使用session。 3、session會在一定時間內保存在服務器上。當訪問增多,會比較占用你服務器的性能,考慮到減輕服務器性能方面,應當使用cookie。 4、單個cookie保存的數據不能超過4K,很多瀏覽器都限制一個站點最多保存20個cookie。 5、可以考慮將登陸信息等重要信息存放為session,其他信息如果需要保留,可以放在cookie中。
理論

cookie和Django中操作cookie

cookie

  • cookie的由來

HTTP協議是無狀態的。

無狀態的意思是每次請求都是獨立的,它的執行情況和結果與前面的請求和之後的請求都無直接關系,

它不會受前面的請求響應情況直接影響,也不會直接影響後面的請求響應情況。

一句有意思的話來描述就是人生只如初見,對服務器來說,每次的請求都是全新的。

狀態可以理解為客戶端和服務器在某次會話中產生的數據,那無狀態的就以為這些數據不會被保留。會

話中產生的數據又是我們需要保存的,也就是說要“保持狀態”。因此Cookie就是在這樣一個場景下誕生。

  • 什麽是cookie

    cookie具體指的是一段小信息,他它是服務器發送出來存儲在瀏覽器上的一組組鍵值對,下次訪問服

    務器時瀏覽器會自動攜帶這些鍵值對,以便服務器提取有用信息。

  • cookie的原理

    cookie的工作原理是:由服務器產生內容,瀏覽器收到請求後保存到本地;當瀏覽器再次訪問時,瀏

    覽器會自動帶上cookie,這樣服務器就能通過cookie的內容來判斷這個是“誰了”。

  • 查看cookie

    開發者工具->Network->Cookies

Django中操作cookie

  • 獲取cookie

    request.COOKIES[‘key‘]
    request.get_signed_cookie(‘key‘, default=RAISE_ERROR, salt=‘‘, max_age=None)
    • get_segned_cookie方法的參數:

      • default:默認值

      • salt:加密鹽

      • max_age:後臺控制過期時間

  • 設置cookie

    req = HrttpRequest(...)
    req = render(request, ...)
    ?
    req.set_cookie(key, values, ...)
    req.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

    def logout(request):
    req = redirect("/login/")
    req.delete_cookie("user") # 刪除用戶瀏覽器上之前設置的user的cookie值
    • cookie版登錄校驗

      def check_login(func):
      @wraps(func)
      def inner(request, *args, **kwargs):
      next_url = request.get_full_path()
      if request.get_signed_cookie("login", salt="SSS", default=None) == "yes":
      # 已經登錄的用戶...
      return func(request, *args, **kwargs)
      else:
      # 沒有登錄的用戶,跳轉剛到登錄頁面
      return redirect("/login/?next={}".format(next_url))
      return inner
      ?
      ?
      def login(request):
      if request.method == "POST":
      username = request.POST.get("username")
      passwd = request.POST.get("password")
      if username == "xxx" and passwd == "dashabi":
      next_url = request.GET.get("next")
      if next_url and next_url != "/logout/":
      response = redirect(next_url)
      else:
      response = redirect("/class_list/")
      response.set_signed_cookie("login", "yes", salt="SSS")
      return response
      return render(request, "login.html")

session和Django中操作session

session

  • session的由來

    Cookie雖然在一定程度上解決了“保持狀態”的需求,但是由於Cookie本身最大支持4096字節,以及

    Cookie本身保存在客戶端,可能被攔截或竊取,因此就需要有一種新的東西,它能支持更多的字節,並

    且他保存在服務器,有較高的安全性。這就是Session。

    問題來了,基於HTTP協議的無狀態特征,服務器根本就不知道訪問者是“誰”。那麽上述的Cookie就

    起到橋接的作用。

    我們可以給每個客戶端的Cookie分配一個唯一的id,這樣用戶在訪問時,通過Cookie,服務器就知

    道來的人是“誰”。然後我們再根據不同的Cookie的id,在服務器上保存一段時間的私密資料,如“賬號密

    碼”等等。

    總結而言:Cookie彌補了HTTP無狀態的不足,讓服務器知道來的人是“誰”;但是Cookie以文本的形

    式保存在本地,自身安全性較差;所以我們就通過Cookie識別不同的用戶,對應的在Session裏保存私密

    的信息以及超過4096字節的文本。

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

Django中操作session

# 獲取、設置、刪除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的key
request.session.session_key
?
# 將所有session失效日期小於當前日期的數據刪除
request.session.clear_expired()
?
# 檢查會話session的key在數據庫中是否存在
request.session.exists("session_key")
?
# 刪除當前會話的所有Session數據
request.session.delete()
  
# 刪除當前的會話數據並刪除會話的Cookie。
request.session.flush()
這用於確保前面的會話數據不可以再次被用戶的瀏覽器訪問
例如,django.contrib.auth.logout() 函數中就會調用它。
?
# 設置會話Session和Cookie的超時時間
request.session.set_expiry(value)
* 如果value是個整數,session會在些秒數後失效。
* 如果value是個datatime或timedelta,session就會在這個時間後失效。
* 如果value是0,用戶關閉瀏覽器session就會失效。
* 如果value是None,session會依賴全局session失效策略。
  • 技術分享圖片

  • session版登錄驗證

    from functools import wraps
    ?
    ?
    def check_login(func):
    @wraps(func)
    def inner(request, *args, **kwargs):
    next_url = request.get_full_path()
    if request.session.get("user"):
    return func(request, *args, **kwargs)
    else:
    return redirect("/login/?next={}".format(next_url))
    return inner
    ?
    ?
    def login(request):
    if request.method == "POST":
    user = request.POST.get("user")
    pwd = request.POST.get("pwd")
    ?
    if user == "alex" and pwd == "alex1234":
    # 設置session
    request.session["user"] = user
    # 獲取跳到登陸頁面之前的URL
    next_url = request.GET.get("next")
    # 如果有,就跳轉回登陸之前的URL
    if next_url:
    return redirect(next_url)
    # 否則默認跳轉到index頁面
    else:
    return redirect("/index/")
    return render(request, "login.html")
    ?
    ?
    @check_login
    def logout(request):
    # 刪除所有當前請求相關的session
    request.session.delete()
    return redirect("/login/")
    ?
    ?
    @check_login
    def index(request):
    current_user = request.session.get("user", None)
    return render(request, "index.html", {"user": current_user})

  • Django中的settings配置

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

    1. 數據庫Session
    SESSION_ENGINE = ‘django.contrib.sessions.backends.db‘ # 引擎(默認)
    ?
    2. 緩存Session
    SESSION_ENGINE = ‘django.contrib.sessions.backends.cache‘ # 引擎
    SESSION_CACHE_ALIAS = ‘default‘ # 使用的緩存別名(默認內存緩存,也可以是memcache),此處別名依賴緩存的設置
    ?
    3. 文件Session
    SESSION_ENGINE = ‘django.contrib.sessions.backends.file‘ # 引擎
    SESSION_FILE_PATH = None # 緩存文件路徑,如果為None,則使用tempfile模塊獲取一個臨時地址tempfile.gettempdir()
    ?
    4. 緩存+數據庫
    SESSION_ENGINE = ‘django.contrib.sessions.backends.cached_db‘ # 引擎
    ?
    5. 加密Cookie Session
    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,默認修改之後才保存(默認)
    ?
    Django中Session相關設置

Django中的session和cookie