djanjo book2 學習筆記 (會話 使用者 和註冊)

風之諾發表於2014-03-04
會話 使用者 和註冊線上手冊地址
http://docs.oneele.com/django/topics


COOKIES
第一次開啟瀏覽器,訪問頁面
Response Headers:
Set-Cookie:csrftoken=369caefb109c7a58ed947660ce99104b; expires=Fri, 27-Feb-2015 08:17:35 GMT; Max-Age=31449600; Path=/
Set-Cookie:csrftoken=8bc7a3911f266e87067ecf9dc71a26ec; expires=Fri, 27-Feb-2015 08:20:40 GMT; Max-Age=31449600; Path=/


Set-Cookie:sessionid=942fc061ff46f73b998e3f3e06ce2eb7; expires=Fri, 14-Mar-2014 08:22:17 GMT; Max-Age=1209600; Path=/


接下來再次訪問同一個頁面
Request Headers:
Cookie:csrftoken=369caefb109c7a58ed947660ce99104b


Cookie:csrftoken=8bc7a3911f266e87067ecf9dc71a26ec; sessionid=61183c29da0f03d5dbbe55e8c696afdc
Cookie:csrftoken=8bc7a3911f266e87067ecf9dc71a26ec; sessionid=942fc061ff46f73b998e3f3e06ce2eb7


from django.contrib.sessions.models import Session
s = Session.objects.get(sessionid='942fc061ff46f73b998e3f3e06ce2eb7')


是時候承認了: 我們有意的避開了Web開發中極其重要的方面。 到目前為止,我們都在假定,網站流量是大
量的匿名使用者帶來的。
這當然不對。 瀏覽器的背後都是活生生的人(至少某些時候是)。 這忽略了重要的一點: 網際網路服務於人而不是
機器。 要開發一個真正令人心動的網站,我們必須面對瀏覽器後面活生生的人。
很不幸,這並不容易。 HTTP被設計為”無狀態”,每次請求都處於相同的空間中。 在一次請求和下一次請求
之間沒有任何狀態保持,我們無法根據請求的任何方面(IP地址,使用者代理等)來識別來自同一人的連續請求。
在本章中你將學會如何搞定狀態的問題。 好了,我們會從較低的層次(cookies)開始,然後過渡到用高層的工
來搞定會話,使用者和註冊的問題。


Cookies
    瀏覽器的開發者在很早的時候就已經意識到, HTTP’s 的無狀態會對Web開發者帶來很大的問題,於是
    (cookies)應運而生。 cookies 是瀏覽器為 Web 伺服器儲存的一小段資訊。 每次瀏覽器從某個伺服器請求頁
    時,它向伺服器回送之前收到的cookies
    來看看它是怎麼工作的。 當你開啟瀏覽器並訪問 google.com ,你的瀏覽器會給Google傳送一個HTTP請求,
    起始部分就象這樣:
        GET / HTTP/1.1
        Host: google.com
    ...
    當 Google響應時,HTTP的響應是這樣的:
    HTTP/1.1 200 OK
        Content‐Type: text/html
        Set‐Cookie: PREF=ID=5b14f22bdaf1e81c:TM=1167000671:LM=1167000671;
                    expires=Sun, 17‐Jan‐2038 19:14:07 GMT;
                    path=/; domain=.google.com
        Server: GWS/2.1
        
        
Django的 Session 框架
    由於存在的限制與安全漏洞,cookies和持續性會話已經成為Web開發中令人頭疼的典範。 好訊息是,Django
    的目標正是高效的“頭疼殺手”,它自帶的session框架會幫你搞定這些問題。
    你可以用session 框架來存取每個訪問者任意資料, 這些資料在伺服器端儲存,並對cookie的收發進行了抽
    象。 Cookies只儲存資料的雜湊會話ID,而不是資料本身,從而避免了大部分的常見cookie問題。
    下面我們來看看如何開啟session功能,並在檢視中使用它。
    


1)開啟 Sessions功能
    Sessions 功能是通過一箇中介軟體(參見第17章)和一個模型(model)來實現的。 要開啟sessions功能,需要以下
    幾步操作:
    1.  編輯 MIDDLEWARE_CLASSES 配置,確保 MIDDLEWARE_CLASSES 中包含
    'django.contrib.sessions.middleware.SessionMiddleware'。
    2.  確認 INSTALLED_APPS 中有 'django.contrib.sessions' (如果你是剛開啟這個應用,別忘了執行
    manage.py syncdb )
    如果專案是用 startproject 來建立的,配置檔案中都已經安裝了這些東西,除非你自己刪除,正常情況下,你
    無需任何設定就可以使用session功能。
    如果不需要session功能,你可以刪除 MIDDLEWARE_CLASSES 設定中的 SessionMiddleware 和 INSTALLED_APPS 設
    置中的 'django.contrib.sessions' 。雖然這隻會節省很少的開銷,但積少成多啊。


2)在檢視中使用Session
    SessionMiddleware 啟用後,每個傳給檢視(view)函式的第一個引數``HttpRequest`` 物件都有一個 session 屬
    性,這是一個字典型的物件。 你可以象用普通字典一樣來用它。 例如,在檢視(view)中你可以這樣用:
    # Set a session value:
    request.session["fav_color"] = "blue"
    # Get a session value ‐‐ this could be called in a different view,
    # or many requests later (or both):
    fav_color = request.session["fav_color"]
    # Clear an item from the session:
    del request.session["fav_color"]
    # Check if the session has a given key:
    if "fav_color" in request.session:
    其他的對映方法,如 keys() 和 items() 對 request.session 同樣有效:
    
在檢視(View)外使用Session
    從內部來看,每個session都只是一個普通的Django model(在 django.contrib.sessions.models 中定義)。
    每個session都由一個隨機的32位元組雜湊串來標識,並儲存於cookie中。 因為它是一個標準的模型,所以你可
    以使用Django資料庫API來存取session。
    >>> from django.contrib.sessions.models import Session
    >>> s = Session.objects.get(pk='2b1189a188b44ad18c35e113ac6ceead')
    >>> s.expire_date
    datetime.datetime(2005, 8, 20, 13, 35, 12)
    你需要使用get_decoded() 來讀取實際的session資料。 這是必需的,因為字典儲存為一種特定的編碼格式。
    >>> s.session_data
    'KGRwMQpTJ19hdXRoX3VzZXJfaWQnCnAyCkkxCnMuMTExY2ZjODI2Yj...'
    >>> s.get_decoded()
    {'user_id': 42}
    
何時儲存Session
    預設的情況下,Django只會在session發生變化的時候才會存入資料庫,比如說,字典賦值或刪除。
    # Session is modified.
    request.session['foo'] = 'bar'
    # Session is modified.
    del request.session['foo']
    # Session is modified.
    request.session['foo'] = {}
    # Gotcha: Session is NOT modified, because this alters
    # request.session['foo'] instead of request.session.
    request.session['foo']['bar'] = 'baz'
    你可以設定 SESSION_SAVE_EVERY_REQUEST 為 True 來改變這一預設行為。
    如果置為True的話,Django會在每收到請求的時候儲存session,即使沒發生變化。
    注意,會話cookie只會在建立和修改的時候才會送出。 但如果 SESSION_SAVE_EVERY_REQUEST 設定為 True ,會
    話cookie在每次請求的時候都會送出。 同時,每次會話cookie送出的時候,其 expires 引數都會更新。
    
在setting 中設定
SESSION_COOKIE_AGE=60*30 30分鐘。
SESSION_EXPIRE_AT_BROWSER_CLOSE False:會話cookie可以在使用者瀏覽器中保持有效期。True:關閉瀏覽器,則Cookie失效。
SESSION_COOKIE_DOMAIN 生效站點
SESSION_COOKIE_NAME cookie中儲存session的名稱
Session使用比較簡單,在request.session是一個字典類。session是儲存在資料庫中的。




瀏覽器關閉即失效會話 vs 持久會話
    你可能注意到了,Google給我們傳送的cookie中有 expires=Sun, 17‐Jan‐2038 19:14:07 GMT; cookie可以有
    過期時間,這樣瀏覽器就知道什麼時候可以刪除cookie了。 如果cookie沒有設定過期時間,當使用者關閉瀏覽器
    的時候,cookie就自動過期了。 你可以改變 SESSION_EXPIRE_AT_BROWSER_CLOSE 的設定來控制session框架的
    這一行為。
    
    預設情況下, SESSION_EXPIRE_AT_BROWSER_CLOSE 設定為 False ,這樣,會話cookie可以在使用者瀏覽器中保持
    有效達 SESSION_COOKIE_AGE 秒(預設設定是兩週,即1,209,600 秒)。 如果你不想使用者每次開啟瀏覽器都必須
    重新登陸的話,用這個引數來幫你。
    如果 SESSION_EXPIRE_AT_BROWSER_CLOSE 設定為 True ,當瀏覽器關閉時,Django會使cookie失效。
    其他的Session設定
    除了上面提到的設定,還有一些其他的設定可以影響Django session框架如何使用cookie,詳見表 14-2.
    
    表 14-2. 影響cookie行為的設定 設定描述預設
    SESSION_COOKIE_DOMAIN使用會話cookie(session cookies)的站點。 將它設成一個 None
            字串,就好象`` “.example.com”`` 以用於跨站點(cross-domain)的cookie,或`` None`` 以用於單個站點。
    SESSION_COOKIE_NAME會話中使用的cookie的名字。 它可以是任意的字串。"sessionid"
    SESSION_COOKIE_SECURE是否在session中使用安全cookie。 如果設定 True , cookie就 False
    會標記為安全, 這意味著cookie只會通過HTTPS來傳輸。
    
技術細節
    如果你還是好奇的話,下面是一些關於session框架內部工作方式的技術細節:
    session 字典接受任何支援序列化的Python物件。 參考Python內建模組pickle的文件以獲取更多資訊。
    Session 資料存在資料庫表 django_session 中
    Session 資料在需要的時候才會讀取。 如果你從不使用 request.session , Django不會動相關資料庫表的
    一根毛。
    Django 只在需要的時候才送出cookie。 如果你壓根兒就沒有設定任何會話資料,它不會 送出會話
    cookie(除非 SESSION_SAVE_EVERY_REQUEST 設定為 True )。
    Django session 框架完全而且只能基於cookie。 它不會後退到把會話ID編碼在URL中(像某些工具
    (PHP,JSP)那樣)。
    這是一個有意而為之的設計。 把session放在URL中不只是難看,更重要的是這讓你的站點 很容易受到攻擊
    ——通過 Referer header進行session ID”竊聽”而實施的攻擊。
    如果你還是好奇,閱讀原始碼是最直接辦法,詳見 django.contrib.sessions 。
    
登入和退出
    Django 提供內建的檢視(view)函式用於處理登入和退出 (以及其他奇技淫巧),但在開始前,我們來看看如何
    和退出。 Django提供兩個函式來執行django.contrib.auth\中的動作 : authenticate()
    和login()。
    認證給出的使用者名稱和密碼,使用 authenticate() 函式。它接受兩個引數,使用者名稱 username 和 密碼
    password ,並在密碼對給出的使用者名稱合法的情況下返回一個 User 物件。 如果密碼不合法,authenti
    回None。
    >>> from django.contrib import auth
    >>> user = auth.authenticate(username='john', password='secret')
    >>> if user is not None:
    ...     print "Correct!"
    ... else:
    ...     print "Invalid password."
    authenticate() 只是驗證一個使用者的證照而已。 而要登入一個使用者,使用 login() 。該函式接受一個
    HttpRequest 物件和一個 User 物件作為引數並使用Django的會話( session )框架把使用者的ID儲存在
    中。
    下面的例子演示瞭如何在一個檢視中同時使用 authenticate() 和 login() 函式:
    from django.contrib import auth
    def login_view(request):
        username = request.POST.get('username', '')
        password = request.POST.get('password', '')
        user = auth.authenticate(username=username, password=password)
        if user is not None and user.is_active:
            # Correct password, and the user is marked "active"
            auth.login(request, user)
            # Redirect to a success page.
            return HttpResponseRedirect("/account/loggedin/")
        else:
            # Show an error page
            return HttpResponseRedirect("/account/invalid/")
    登出一個使用者,在你的檢視中使用 django.contrib.auth.logout() 。 它接受一個HttpRequest物件並
    回值。
    from django.contrib import auth
    def logout_view(request):
        auth.logout(request)
        # Redirect to a success page.
        return HttpResponseRedirect("/account/loggedout/")
    注意,即使使用者沒有登入, logout() 也不會丟擲任何異常。

相關文章