會話(Session)


Django的 Session 框架

由于存在的限制與安全漏洞绳军,cookies和持續(xù)性會話已經(jīng)成為Web開發(fā)
的隱患矢腻,Django自帶的session框架會幫你搞定這些問題耳贬,你可以用session 框架來存取每個訪問者任意數(shù)據(jù)猎唁, 這些數(shù)據(jù)在服務(wù)器端存儲,并對cookie的收發(fā)進(jìn)行了抽象腐魂。 Cookies只存儲數(shù)據(jù)的哈希會話ID逐纬,而不是數(shù)據(jù)本身,從而避免了大部分的常見cookie問題豁生。


開啟Sessions功能

Sessions 功能是通過一個中間件和一個模型來實現(xiàn)的。 要打開sessions功能育叁,需要以下幾步操作:

  • 確保 MIDDLEWARE_CLASSES 中包含 'django.contrib.sessions.middleware.SessionMiddleware'芍殖。

  • 確保 INSTALLED_APPS 中有 'django.contrib.sessions' (如果你是剛打開這個應(yīng)用,別忘記同步數(shù)據(jù)庫 )

正常情況下龟梦,你無需任何設(shè)置就可以使用session功能窃躲。


在視圖中使用Session

SessionMiddleware 激活后,每個傳給視圖(view)函數(shù)的第一個參數(shù)HttpRequest對象都有一個 session 屬性躁倒,這是一個字典型的對象。 你可以象用普通字典一樣來用它:

# 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 同樣有效

字典的keys() values() items()方法

字典的items(), keys(), values()都返回一個list
dict = { 1 : 2, 'a' : 'b', 'hello' : 'world' }  
dict.values()  
['b', 2, 'world']  
dict.keys()  
['a', 1, 'hello']  
dict.items()  
[('a', 'b'), (1, 2), ('hello', 'world')]  

用正常的字符串作為key來訪問字典 request.session 福贞, 而不是整數(shù)、對象或其它什么的挖帘。Session字典中以下劃線開頭的key值是Django內(nèi)部保留key值

看一個簡單的例子:在用戶發(fā)了一次評論后將has_commented設(shè)置為True。 這是個簡單(但不很安全)的逻族、防止用戶多次評論的方法骄崩。

def post_comment(request):
    if request.method != 'POST':
        raise Http404('Only POSTs are allowed')
    if 'comment' not in request.POST:
        raise Http404('Comment not submitted')
    if request.session.get('has_commented', False):
        return HttpResponse("You've already commented.")

    c = comments.Comment(comment=request.POST['comment'])
    c.save()
    request.session['has_commented'] = True
    return HttpResponse('Thanks for your comment!')

一個很簡單的站點登錄視圖(view):在實踐中,這是很爛的用戶登錄方式要拂,稍后討論的認(rèn)證(authentication )框架會幫你以更健壯和有利的方式來處理這些問題。 這些非常簡單的例子只是想讓你知道這一切是如何工作的搏嗡。

def login(request):
    if request.method != 'POST':
        raise Http404('Only POSTs are allowed')
    try:
        m = Member.objects.get(username=request.POST['username'])
        if m.password == request.POST['password']:
            request.session['member_id'] = m.id
            return HttpResponseRedirect('/you-are-logged-in/')
    except Member.DoesNotExist:
        return HttpResponse("Your username and password didn't match.")
def logout(request):
    try:
        del request.session['member_id']
    except KeyError:
        pass
    return HttpResponse("You're logged out.")

設(shè)置測試Cookies

你不能指望所有的瀏覽器都可以接受cookie拉一。 因此,為了使用方便磅氨,Django提供了一個簡單的方法來測試用戶的瀏覽器是否接受cookie抽碌。 你只需在視圖(view)中調(diào)用 request.session.set_test_cookie()
,并在后續(xù)的視圖(view)左权,而不是當(dāng)前的視圖(view)中檢查 request.session.test_cookie_worked()

def login(request):

    # If we submitted the form...
    if request.method == 'POST':

        # Check that the test cookie worked (we set it below):
        if request.session.test_cookie_worked():

            # The test cookie worked, so delete it.
            request.session.delete_test_cookie()

            # In practice, we'd need some logic to check username/password
            # here, but since this is an example...
            return HttpResponse("You're logged in.")

        # The test cookie failed, so display an error message. If this
        # were a real site, we'd want to display a friendlier message.
        else:
            return HttpResponse("Please enable cookies and try again.")

    # If we didn't post, send the test cookie along with the login form.
    request.session.set_test_cookie()
    return render_to_response('foo/login_form.html')

Django Session工作原理:

下面是一些關(guān)于session框架內(nèi)部工作方式的技術(shù)細(xì)節(jié):

  • session 字典接受任何支持序列化的Python對象痴颊。 參考Python內(nèi)建模塊pickle的文檔以獲取更多信息。

  • Session 數(shù)據(jù)存在數(shù)據(jù)庫表 django_session 中

  • Session 數(shù)據(jù)在需要的時候才會讀取锌杀。 如果你從不使用 request.session 糕再, Django不會動相關(guān)數(shù)據(jù)庫表的一根毛。

  • Django 只在需要的時候才送出cookie突想。 如果你壓根兒就沒有設(shè)置任何會話數(shù)據(jù),它不會 送出會話cookie(除非 SESSION_SAVE_EVERY_REQUEST 設(shè)置為 True )袭灯。

  • Django session 框架完全而且只能基于cookie绑嘹。 它不會后退到把會話ID編碼在URL中(像某些工具(PHP,JSP)那樣)。這是一個有意而為之的設(shè)計工腋。 把session放在URL中不只是難看,更重要的是這讓你的站點 很容易受到攻擊(通過 Referer header進(jìn)行session ID”竊聽”而實施的攻擊)

如果你還是好奇构挤,閱讀源代碼是最直接辦法惕鼓,django.contrib.sessions 唐础。


在視圖(View)外使用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)

s.session_data
'KGRwMQpTJ19hdXRoX3VzZXJfaWQnCnAyCkkxCnMuMTExY2ZjODI2Yj...'
s.get_decoded()  #需要使用get_decoded() 來讀取實際的session數(shù)據(jù)一膨,因為字典存儲為一種特定的編碼格式
{'user_id': 42}

何時保存Session:

缺省的情況下,Django只會在session發(fā)生變化的時候才會存入數(shù)據(jù)庫豹绪,比如說,字典賦值或刪除蝉衣。你可以設(shè)置 SESSION_SAVE_EVERY_REQUEST 為 True 來改變這一缺省行為巷蚪。Django會在每次收到請求的時候保存session,即使沒發(fā)生變化屁柏。
會話cookie只會在創(chuàng)建和修改的時候才會送出淌喻。 但如果 SESSION_SAVE_EVERY_REQUEST 設(shè)置為 True ,會話cookie在每次請求的時候都會送出裸删。 同時,每次會話cookie送出的時候,其 expires 參數(shù)都會更新豌注。


瀏覽器關(guān)閉即失效會話 vs 持久會話:

缺省情況下灯萍, SESSION_EXPIRE_AT_BROWSER_CLOSE 設(shè)置為 False ,這樣齿风,會話cookie可以在用戶瀏覽器中保持有效達(dá) SESSION_COOKIE_AGE 秒(缺省設(shè)置是兩周)绑洛。 如果你不想用戶每次打開瀏覽器都必須重新登陸的話,用這個參數(shù)來幫你脸候。
如果 SESSION_EXPIRE_AT_BROWSER_CLOSE 設(shè)置為 True 绑蔫,當(dāng)瀏覽器關(guān)閉時,Django會使cookie失效携添。

影響cookie行為的設(shè)置:

設(shè)置 缺省值 描述
SESSION_COOKIE_DOMAIN 使用會話cookie(session cookies)的站點篓叶。 將它設(shè)成一個字符串,就好象“.example.com” 以用于跨站點(cross-domain)的cookie左敌,或None 以用于單個站點嗦董。 None
SESSION_COOKIE_NAME 會話中使用的cookie的名字京革。 它可以是任意的字符串 "sessionid"
SESSION_COOKIE_SECURE 是否在session中使用安全cookie。 如果設(shè)置 True , cookie就會標(biāo)記為安全咬扇, 這意味著cookie只會通過HTTPS來傳輸廊勃。 False
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市梭灿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌堡妒,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件搬泥,死亡現(xiàn)場離奇詭異忿檩,居然都是意外死亡爆阶,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進(jìn)店門兽掰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人窖壕,你說我怎么就攤上這事≌胺恚” “怎么了鸳吸?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長速勇。 經(jīng)常有香客問我晌砾,道長,這世上最難降的妖魔是什么烦磁? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任养匈,我火速辦了婚禮,結(jié)果婚禮上都伪,老公的妹妹穿的比我還像新娘呕乎。我一直安慰自己,他們只是感情好陨晶,可當(dāng)我...
    茶點故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布猬仁。 她就那樣靜靜地躺著,像睡著了一般的烁。 火紅的嫁衣襯著肌膚如雪撮躁。 梳的紋絲不亂的頭發(fā)上买雾,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天嗤军,我揣著相機與錄音叙赚,去河邊找鬼震叮。 笑死苇瓣,一個胖子當(dāng)著我的面吹牛偿乖,可吹牛的內(nèi)容都是我干的贪薪。 我是一名探鬼主播竣稽,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼毫别,長吁一口氣:“原來是場噩夢啊……” “哼拧烦!你這毒婦竟也來了恋博?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎硅蹦,沒想到半個月后童芹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體假褪,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年缀遍,在試婚紗的時候發(fā)現(xiàn)自己被綠了域醇。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片歹苦。...
    茶點故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖号杠,靈堂內(nèi)的尸體忽然破棺而出姨蟋,到底是詐尸還是另有隱情立帖,我是刑警寧澤晓勇,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布绰筛,位于F島的核電站铝噩,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏毛甲。R本人自食惡果不足惜玻募,卻給世界環(huán)境...
    茶點故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望坑雅。 院中可真熱鬧裹粤,春花似錦遥诉、人聲如沸矮锈。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽臭杰。三九已至渴杆,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間脉顿,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留弟疆,地道東北人怠苔。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓柑司,卻偏偏與公主長得像,于是被迫代替她去往敵國和親故爵。 傳聞我的和親對象是個殘疾皇子诬垂,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,700評論 2 354

推薦閱讀更多精彩內(nèi)容