# 如何使用會話 #
Django 提供對匿名會話的完全支持。其會話框架讓你根據各個站點的訪問者存儲和訪問任意數據。它在服務器端存儲數據并抽象Cookie 的發送和接收。Cookie 包含會話的ID —— 不是數據本身(除非你使用基于Cookie 的后端)。
## 啟用會話 ##
會話是通過一個中間件實現的。
為了啟用會話功能,需要這樣做:
編輯`MIDDLEWARE_CLASSES` 設置并確保它包含'`django.contrib.sessions.middleware.SessionMiddleware`'。`django-admin startproject`創建的默認的`settings.py`已經啟用`SessionMiddleware`。
如果你不想使用會話,你也可以從`MIDDLEWARE_CLASSES`中刪除`SessionMiddleware`行,并從`INSTALLED_APPS`中刪除'`django.contrib.sessions`'。它將節省一些性能消耗。
## 配置會話引擎 ##
默認情況下,Django 存儲會話到你的數據庫中(使用`django.contrib.sessions.models.Session`模型)。雖然這很方便,但是在某些架構中存儲會話在其它地方會更快,所以可以配置Django 來存儲會話到你的文件系統上或緩存中。
### 使用數據庫支持的會話 ###
如果你想使用數據庫支持的會話,你需要添加'`django.contrib.sessions`' 到你的`INSTALLED_APPS`設置中。
在配置完成之后,請運行`manage.py migrate`來安裝保存會話數據的一張數據庫表。
### 使用基于緩存的會話 ###
為了更好的性能,你可能想使用一個基于緩存的會話后端。
為了使用Django 的緩存系統來存儲會話數據,你首先需要確保你已經配置好你的緩存;詳細信息參見緩存的文檔。
> 警告
>
> 你應該只在使用Memcached 緩存系統時才使用基于緩存的會話。基于本地內存的緩存系統不會長時間保留數據,所以不是一個好的選擇,而且直接使用文件或數據庫會話比通過文件或數據庫緩存系統要快。另外,基于本地內存的緩存系統不是多進程安全的,所以對于生產環境可能不是一個好的選擇。
如果你在`CACHES`中定義多個緩存,Django 將使用默認的緩存。若要使用另外一種緩存,請設置`SESSION_CACHE_ALIAS`為該緩存的名字。
配置好緩存之后,對于如何在緩存中存儲數據你有兩個選擇:
+ 對于簡單的緩存會話存儲,可以設置`SESSION_ENGINE` 為"`django.contrib.sessions.backends.cache`" 。此時會話數據將直接存儲在你的緩存中。然而,緩存數據將可能不會持久:如果緩存填滿或者緩存服務器重啟,緩存數據可能會被清理掉。
+ 若要持久的緩存數據,可以設置`SESSION_ENGINE`為"`django.contrib.sessions.backends.cached_db`"。它的寫操作使用緩存 —— 對緩存的每次寫入都將再寫入到數據庫。對于讀取的會話,如果數據不在緩存中,則從數據庫讀取。
兩種會話的存儲都非常快,但是簡單的緩存更快,因為它放棄了持久性。大部分情況下,`cached_db`后端已經足夠快,但是如果你需要榨干最后一點的性能,并且接收讓會話數據丟失,那么你可使用`cache`后端。
如果你使用`cached_db` 會話后端,你還需要遵循[使用數據庫支持的會話](http://python.usyiyi.cn/django/topics/http/sessions.html#using-database-backed-sessions)中的配置說明。
```
Changed in Django 1.7:
在1.7 版之前,`cached_db` 永遠使用`default`緩存而不是`SESSION_CACHE_ALIAS`。
```
### 使用基于文件的緩存 ###
要使用基于文件的緩存,請設置`SESSION_ENGINE`為"`django.contrib.sessions.backends.file`"。
你可能還想設置`SESSION_FILE_PATH`(它的默認值來自`tempfile.gettempdir()`的輸出,大部分情況是`/tmp`)來控制Django在哪里存儲會話文件。請保證你的Web 服務器具有讀取和寫入這個位置的權限。
### 使用基于Cookie 的會話 ###
要使用基于Cookie 的會話,請設置`SESSION_ENGINE` 為"`django.contrib.sessions.backends.signed_cookies`"。此時,會話數據的存儲將使用Django 的加密簽名 工具和`SECRET_KEY` 設置。
> 注
>
> 建議保留SESSION_COOKIE_HTTPONLY 設置為True 以防止從JavaScript 中訪問存儲的數據。
> 警告
>
> 如果`SECRET_KEY` 沒有保密并且你正在使用 `PickleSerializer`,這可能導致遠端執行任意的代碼。
>
> 擁有`SECRET_KEY` 的攻擊者不僅可以生成篡改的會話數據而你的站點將會信任這些數據,而且可以遠程執行任何代碼,就像數據是通過pickle 序列化過的一樣。
>
> 如果你使用基于Cookie 的會話,請格外注意你的安全秘鑰對于任何可以遠程訪問的系統都是永遠完全保密的。
>
> 會話數據經過簽名但沒有加密。
>
> 如果使用基于Cookie的會話,則會話數據可以被客戶端讀取。
>
> MAC(消息認證碼)被用來保護數據不被客戶端修改,所以被篡改的會話數據將是變成不合法的。如果保存Cookie的客戶端(例如你的瀏覽器)不能保存所有的會話Cookie或丟失數據,會話同樣會變得不合法。盡管Django 對數據進行壓縮,仍然完全有可能超過每個Cookie [常見的4096 個字節的限制](http://tools.ietf.org/html/rfc2965#section-5.3)。
>
> 沒有更新保證
>
> 還要注意,雖然MAC可以保證數據的權威性(由你的站點生成,而不是任何其他人)和完整性(包含全部的數據并且是正確的),它不能保證是最新的,例如返回給你發送給客戶端的最新的數據。這意味著對于某些會話數據的使用,基于Cookie 可能讓你受到重放攻擊。其它方式的會話后端在服務器端保存每個會話并在用戶登出時使它無效,基于Cookie 的會話在用戶登出時不會失效。因此,如果一個攻擊者盜取用戶的Cookie,它們可以使用這個Cookie 來以這個用戶登錄即使用戶已登出。Cookies 只能被當做是“過期的”,如果它們比你的SESSION_COOKIE_AGE要舊。
>
> 性能
>
> 最后,Cookie 的大小對[你的網站的速度](http://yuiblog.com/blog/2007/03/01/performance-research-part-3/) 有影響。
## 在視圖中使用會話 ##
當`SessionMiddleware` 激活時,每個`HttpRequest` 對象 —— 傳遞給Django 視圖函數的第一個參數 —— 將具有一個`session` 屬性,它是一個類字典對象。
你可以在你的視圖中任何地方讀取并寫入 `request.session`。你可以多次編輯它。
`class backends.base.SessionBase`
這是所有會話對象的基類。它具有以下標準的字典方法:
`__getitem__(key)`
例如:`fav_color = request.session['fav_color']`
`__setitem__(key, value)`
例如:`request.session['fav_color'] = 'blue'`
`__delitem__(key)`
例如:`del request.session['fav_color']`。如果給出的key 在會話中不存在,將拋出 `KeyError`。
`__contains__(key)`
例如:`'fav_color' in request.session`
`get(key, default=None)`
例如:`fav_color = request.session.get('fav_color', 'red')`
`pop(key)`
例如:`fav_color = request.session.pop('fav_color')`
`keys()`
`items()`
`setdefault()`
`clear()`
它還具有這些方法:
`flush()`
刪除當前的會話數據并刪除會話的Cookie。這用于確保前面的會話數據不可以再次被用戶的瀏覽器訪問(例如,`django.contrib.auth.logout()` 函數中就會調用它)。
```
Changed in Django 1.8:
刪除會話Cookie 是Django 1.8 中的新行為。以前,該行為用于重新生成會話中的值,這個值會在Cookie 中發回給用戶。
```
`set_test_cookie()`
設置一個測試的Cookie 來驗證用戶的瀏覽器是否支持Cookie。因為Cookie 的工作方式,只有到用戶的下一個頁面才能驗證。更多信息參見下文的設置測試的Cookie。
`test_cookie_worked()`
返回`True` 或`False`,取決于用戶的瀏覽器時候接受測試的Cookie。因為Cookie的工作方式,你必須在前面一個單獨的頁面請求中調用`set_test_cookie()`。更多信息參見下文的設置測試的Cookie。
`delete_test_cookie()`
刪除測試的Cookie。使用這個函數來自己清理。
`set_expiry(value)`
設置會話的超時時間。你可以傳遞一系列不同的值:
+ 如果`value` 是一個整數,會話將在這么多秒沒有活動后過期。例如,調用`request.session.set_expiry(300)` 將使得會話在5分鐘后過期。
+ 若果value 是一個 `datetime` 或`timedelta` 對象,會話將在這個指定的日期/時間過期。注意`datetime` 和`timedelta` 值只有在你使用P`ickleSerializer` 時才可序列化。
+ 如果`value` 為0,那么用戶會話的Cookie將在用戶的瀏覽器關閉時過期。
+ 如果`value` 為`None`,那么會話轉向使用全局的會話過期策略。
過期的計算不考慮讀取會話的操作。會話的過期從會話上次修改的時間開始計算。
`get_expiry_age()`
返回會話離過期的秒數。對于沒有自定義過期的會話(或者設置為瀏覽器關閉時過期的會話),它將等于`SESSION_COOKIE_AGE`。
該函數接收兩個可選的關鍵字參數:
+ `modification`:會話的最后一次修改時間,類型為一個`datetime` 對象。默認為當前的時間。
+ `expiry`:會話的過期信息,類型為一個`datetime` 對象、一個整數(以秒為單位)或`None`。默認為通過`set_expiry()`保存在會話中的值,如果沒有則為`None`。
`get_expiry_date()`
返回過期的日期。對于沒有自定義過期的會話(或者設置為瀏覽器關閉時過期的會話),它將等于從現在開始`SESSION_COOKIE_AGE`秒后的日期。
這個函數接受與`get_expiry_age()`一樣的關鍵字參數。
`get_expire_at_browser_close()`
返回`True` 或`False`,取決于用戶的會話Cookie在用戶瀏覽器關閉時會不會過期。
`clear_expired()`
從會話的存儲中清除過期的會話。這個類方法被`clearsessions`調用。
`cycle_key()`
創建一個新的會話,同時保留當前的會話數據。`django.contrib.auth.login()` 調用這個方法來減緩會話的固定。
### 會話的序列化 ###
在1.6 版以前,在保存會話數據到后端之前Django 默認使用pickle 來序列化它們。如果你使用的是簽名的Cookie 會話后端 并且`SECRET_KEY` 被攻擊者知道(Django 本身沒有漏洞會導致它被泄漏),攻擊者就可以在會話中插入一個字符串,在unpickle 之后可以在服務器上執行任何代碼。在因特網上這個攻擊技術很簡單并很容易查到。盡管Cookie 會話的存儲對Cookie 保存的數據進行了簽名以防止篡改,`SECRET_KEY` 的泄漏會立即使得可以執行遠端的代碼。
這種攻擊可以通過JSON而不是pickle序列化會話數據來減緩。為了幫助這個功能,Django 1.5.3 引入一個新的設置,`SESSION_SERIALIZER`,來自定義會話序列化的格式。為了向后兼容,這個設置在Django 1.5.x 中默認為`django.contrib.sessions.serializers.PickleSerializer`,但是為了增強安全性,在Django 1.6 中默認為`django.contrib.sessions.serializers.JSONSerializer`。即使在編寫你自己的序列化方法講述的說明中,我們也強烈建議依然使用JSON 序列化,特別是在你使用的是Cookie 后端時。
#### 綁定的序列化方法 ####
`class serializers.JSONSerializer`
對 `django.core.signing`中的JSON 序列化方法的一個包裝。只可以序列基本的數據類型。
另外,因為JSON 只支持字符串作為鍵,注意使用非字符串作為`request.session` 的鍵將不工作:
```
>>> # initial assignment
>>> request.session[0] = 'bar'
>>> # subsequent requests following serialization & deserialization
>>> # of session data
>>> request.session[0] # KeyError
>>> request.session['0']
'bar'
```
參見[編寫你自己的序列化器](http://python.usyiyi.cn/django/topics/http/sessions.html#custom-serializers) 一節以獲得更多關于JSON 序列化的限制。
`class serializers.PickleSerializer`
支持任意Python 對象,但是正如上面描述的,可能導致遠端執行代碼的漏洞,如果攻擊者知道了`SECRET_KEY`。
#### 編寫你自己的序列化器 ####
注意,與`PickleSerializer`不同,`JSONSerializer` 不可以處理任意的Python 數據類型。這是常見的情況,需要在便利性和安全性之間權衡。如果你希望在JSON 格式的會話中存儲更高級的數據類型比如`datetime` 和 `Decimal`,你需要編寫一個自定義的序列化器(或者在保存它們到`request.session`中之前轉換這些值到一個可JSON 序列化的對象)。雖然序列化這些值相當簡單直接 (`django.core.serializers.json.DateTimeAwareJSONEncoder` 可能幫得上忙),編寫一個解碼器來可靠地取出相同的內容卻能困難。例如,返回一個`datetime` 時,它可能實際上是與`datetime` 格式碰巧相同的一個字符串)。
你的序列化類必須實現兩個方法,`dumps(self, obj)` 和`loads(self, data)` 來分別序列化和去序列化會話數據的字典。
### 會話對象指南 ###
`在request.session` 上使用普通的Python 字符串作為字典的鍵。這主要是為了方便而不是一條必須遵守的規則。
以一個下劃線開始的會話字典的鍵被Django保留作為內部使用。
不要新的對象覆蓋`request.session`,且不要訪問或設置它的屬性。要像Python 字典一樣使用它。
### 例子 ###
下面這個簡單的視圖在一個用戶提交一個評論后設置`has_commented` 變量為`True`。它不允許一個用戶多次提交評論:
```
def post_comment(request, new_comment):
if request.session.get('has_commented', False):
return HttpResponse("You've already commented.")
c = comments.Comment(comment=new_comment)
c.save()
request.session['has_commented'] = True
return HttpResponse('Thanks for your comment!')
```
登錄站點一個“成員”的最簡單的視圖:
```
def login(request):
m = Member.objects.get(username=request.POST['username'])
if m.password == request.POST['password']:
request.session['member_id'] = m.id
return HttpResponse("You're logged in.")
else:
return HttpResponse("Your username and password didn't match.")
```
...下面是登出一個成員的視圖,已經上面的login():
```
def logout(request):
try:
del request.session['member_id']
except KeyError:
pass
return HttpResponse("You're logged out.")
```
標準的`django.contrib.auth.logout()` 函數實際上所做的內容比這個要多一點以防止意外的數據泄露。它調用的`request.session`的`flush()`方法。我們使用這個例子來演示如何利用會話對象來工作,而不是一個完整的`logout()`實現。
## 設置測試的Cookie ##
為了方便,Django 提供一個簡單的方法來測試用戶的瀏覽器時候接受Cookie。只需在一個視圖中調用`request.session`的`set_test_cookie()`方法,并在接下來的視圖中調用`test_cookie_worked()` —— 不是在同一個視圖中調用。
由于Cookie的工作方式,在`set_test_cookie()` 和`test_cookie_worked()` 之間這種笨拙的分離是必要的。當你設置一個Cookie,直到瀏覽器的下一個請求你不可能真實知道一個瀏覽器是否接受了它。
使用`delete_test_cookie()` 來自己清除測試的Cookie是一個很好的實踐。請在你已經驗證測試的Cookie 已經工作后做這件事。
下面是一個典型的使用示例:
```
def login(request):
if request.method == 'POST':
if request.session.test_cookie_worked():
request.session.delete_test_cookie()
return HttpResponse("You're logged in.")
else:
return HttpResponse("Please enable cookies and try again.")
request.session.set_test_cookie()
return render_to_response('foo/login_form.html')
```
## 在視圖外使用會話 ##
> 注
>
> 這一節中的示例直接從`django.contrib.sessions.backends.db`中導`入SessionStore` 對象。在你的代碼中,你應該從`SESSION_ENGINE` 指定的會話引擎中導入`SessionStore`,如下所示:
```
>>> from importlib import import_module
>>> from django.conf import settings
>>> SessionStore = import_module(settings.SESSION_ENGINE).SessionStore
```
在視圖的外面有一個API 可以使用來操作會話的數據:
```
>>> from django.contrib.sessions.backends.db import SessionStore
>>> s = SessionStore()
>>> # stored as seconds since epoch since datetimes are not serializable in JSON.
>>> s['last_login'] = 1376587691
>>> s.save()
>>> s.session_key
'2b1189a188b44ad18c35e113ac6ceead'
>>> s = SessionStore(session_key='2b1189a188b44ad18c35e113ac6ceead')
>>> s['last_login']
1376587691
```
為了減緩會話固話攻擊,不存在的會話的鍵將重新生成:
```
>>> from django.contrib.sessions.backends.db import SessionStore
>>> s = SessionStore(session_key='no-such-session-here')
>>> s.save()
>>> s.session_key
'ff882814010ccbc3c870523934fee5a2'
```
如果你使用的是`django.contrib.sessions.backends.db` 后端,每個會話只是一個普通的Django 模型。`Session` 模型定義在 `django/contrib/sessions/models.py`中。因為它是一個普通的模型,你可以使用普通的Django 數據庫API 來訪問會話:
```
>>> 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()` 以獲得會話的字典。這是必需的,因為字典是以編碼后的格式保存的:
```
>>> s.session_data
'KGRwMQpTJ19hdXRoX3VzZXJfaWQnCnAyCkkxCnMuMTExY2ZjODI2Yj...'
>>> s.get_decoded()
{'user_id': 42}
```
## 會話何時保存 ##
默認情況下,Django 只有在會話被修改時才會保存會話到數據庫中 —— 即它的字典中的任何值被賦值或刪除時:
```
# 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'
```
上面例子的最后一種情況,我們可以通過設置會話對象的`modified`屬性顯式地告訴會話對象它已經被修改過:
```
request.session.modified = True
```
若要修改這個默認的行為,可以設置 `SESSION_SAVE_EVERY_REQUEST` 為`True`。當設置為`True`時,Django 將對每個請求保存會話到數據庫中。
注意會話的Cookie 只有在一個會話被創建或修改后才會發送。如果`SESSION_SAVE_EVERY_REQUEST` 為`True`,會話的Cookie 將在每個請求中發送。
類似地,會話Cookie 的`expires` 部分在每次發送會話Cookie 時更新。
如果響應的狀態碼時500,則會話不會被保存。
## 瀏覽器時長的會話 VS. 持久的會話 ##
你可以通過`SESSION_EXPIRE_AT_BROWSER_CLOSE`設置來控制會話框架使用瀏覽器時長的會話,還是持久的會話。
默認情況下,`SESSION_EXPIRE_AT_BROWSER_CLOSE`設置為`False`,表示會話的Cookie 保存在用戶的瀏覽器中的時間為`SESSION_COOKIE_AGE`。如果你不想讓大家每次打開瀏覽器時都需要登錄時可以這樣使用。
如果`SESSION_EXPIRE_AT_BROWSER_CLOSE` 設置為`True`,Django 將使用瀏覽器時長的Cookie —— 用戶關閉他們的瀏覽器時立即過期。如果你想讓大家在每次打開瀏覽器時都需要登錄時可以這樣使用。
這個設置是一個全局的默認值,可以通過顯式地調`request.session` 的`set_expiry()` 方法來覆蓋,在上面的在視圖中使用會話中有描述。
> 注
>
> 某些瀏覽器(例如Chrome)提供一種設置,允許用戶在關閉并重新打開瀏覽器后繼續使用會話。在某些情況下,這可能干擾`SESSION_EXPIRE_AT_BROWSER_CLOSE` 設置并導致會話在瀏覽器關閉后不會過期。在測試啟用`SESSION_EXPIRE_AT_BROWSER_CLOSE`設置的Django 應用時請注意這點。
## 清除存儲的會話 ##
隨著用戶在你的網站上創建新的會話,會話數據可能會在你的會話存儲倉庫中積累。如果你正在使用數據庫作為后端,`django_session` 數據庫表將持續增長。如果你正在使用文件作為后端,你的臨時目錄包含的文件數量將持續增長。
要理解這個問題,考慮一下數據庫后端發生的情況。當一個用戶登入時,Django 添加一行到`django_session` 數據庫表中。每次會話數據更新時,Django 將更新這行。如果用戶手工登出,Django 將刪除這行。但是如果該用戶不登出,該行將永遠不會刪除。以文件為后端的過程類似。
Django 不提供自動清除過期會話的功能。因此,定期地清除會話是你的任務。Django 提供一個清除用的管理命令來滿足這個目的:`clearsessions`。建議定義調用這個命令,例如作為一個每天運行的Cron 任務。
注意,以緩存為后端不存在這個問題,因為緩存會自動刪除過期的數據。以cookie 為后端也不存在這個問題,因為會話數據通過用戶的瀏覽器保存。
## 設置 ##
一些[Django 設置](http://python.usyiyi.cn/django/ref/settings.html#settings-sessions) 讓你可以控制會話的行為:
+ [SESSION_CACHE_ALIAS](http://python.usyiyi.cn/django/ref/settings.html#std:setting-SESSION_CACHE_ALIAS)
+ [SESSION_COOKIE_AGE](http://python.usyiyi.cn/django/ref/settings.html#std:setting-SESSION_COOKIE_AGE)
+ [SESSION_COOKIE_DOMAIN](http://python.usyiyi.cn/django/ref/settings.html#std:setting-SESSION_COOKIE_DOMAIN)
+ [SESSION_COOKIE_HTTPONLY](http://python.usyiyi.cn/django/ref/settings.html#std:setting-SESSION_COOKIE_HTTPONLY)
+ [SESSION_COOKIE_NAME](http://python.usyiyi.cn/django/ref/settings.html#std:setting-SESSION_COOKIE_NAME)
+ [SESSION_COOKIE_PATH](http://python.usyiyi.cn/django/ref/settings.html#std:setting-SESSION_COOKIE_PATH)
+ [SESSION_COOKIE_SECURE](http://python.usyiyi.cn/django/ref/settings.html#std:setting-SESSION_COOKIE_SECURE)
+ [SESSION_ENGINE](http://python.usyiyi.cn/django/ref/settings.html#std:setting-SESSION_ENGINE)
+ [SESSION_EXPIRE_AT_BROWSER_CLOSE](http://python.usyiyi.cn/django/ref/settings.html#std:setting-SESSION_EXPIRE_AT_BROWSER_CLOSE)
+ [SESSION_FILE_PATH](http://python.usyiyi.cn/django/ref/settings.html#std:setting-SESSION_FILE_PATH)
+ [SESSION_SAVE_EVERY_REQUEST](http://python.usyiyi.cn/django/ref/settings.html#std:setting-SESSION_SAVE_EVERY_REQUEST)
## 會話的安全 ##
一個站點下的子域名能夠在客戶端為整個域名設置Cookie。如果子域名不收信任的用戶控制且允許來自子域名的Cookie,那么可能發生會話固定。
例如,一個攻擊者可以登錄`good.example.com`并為他的賬號獲取一個合法的會話。如果該攻擊者具有`bad.example.com`的控制權,那么他可以使用這個域名來發送他的會話ID給你,因為子域名允許在`*.example.com`上設置Cookie。當你訪問`good.example.com`時,你將被登錄成攻擊者而沒有注意到并輸入你的敏感的個人信息(例如,信用卡信息)到攻擊者的賬號中。
另外一個可能的攻擊是,如果`good.example.com`設置它的 `SESSION_COOKIE_DOMAIN` 為"`.example.com`" ,這將導致來自該站點的會話Cookie 被發送到`bad.example.com`。
## 技術細節 ##
+ 當使用`JSONSerializer`時,會話字典接收任何可json 序列化的值,當使用`PickleSerializer`時接收任何pickleable 的Python對象。更多信息參見`pickle` 模塊。
+ 會話數據存儲在數據中名為`django_session` 的表中。
+ Django 只發送它需要的Cookie。如果你沒有設置任何會話數據,它將不會發送會話Cookie。
## URL 中的會話ID ##
Django 會話框架完全地、唯一地基于Cookie。它不像PHP一樣,實在沒辦法就把會話的ID放在URL 中。這是一個故意的設計。這個行為不僅使得URL變得丑陋,還使得你的網站易于受到通過"Referer" 頭部竊取會話ID的攻擊。
> 譯者:[Django 文檔協作翻譯小組](http://python.usyiyi.cn/django/index.html),原文:[Sessions](https://docs.djangoproject.com/en/1.8/topics/http/sessions/)。
>
> 本文以 [CC BY-NC-SA 3.0](http://creativecommons.org/licenses/by-nc-sa/3.0/cn/) 協議發布,轉載請保留作者署名和文章出處。
>
> [Django 文檔協作翻譯小組](http://python.usyiyi.cn/django/index.html)人手緊缺,有興趣的朋友可以加入我們,完全公益性質。交流群:467338606。
- 新手入門
- 從零開始
- 概覽
- 安裝
- 教程
- 第1部分:模型
- 第2部分:管理站點
- 第3部分:視圖和模板
- 第4部分:表單和通用視圖
- 第5部分:測試
- 第6部分:靜態文件
- 高級教程
- 如何編寫可重用的應用
- 為Django編寫首個補丁
- 模型層
- 模型
- 模型語法
- 元選項
- 模型類
- 查詢集
- 執行查詢
- 查找表達式
- 模型的實例
- 實例方法
- 訪問關聯對象
- 遷移
- 模式編輯器
- 編寫遷移
- 高級
- 管理器
- 原始的SQL查詢
- 聚合
- 多數據庫
- 自定義查找
- 條件表達式
- 數據庫函數
- 其它
- 遺留的數據庫
- 提供初始數據
- 優化數據庫訪問
- 視圖層
- 基礎
- URL配置
- 視圖函數
- 快捷函數
- 裝飾器
- 參考
- 內建的視圖
- TemplateResponse 對象
- 文件上傳
- 概覽
- File 對象
- 儲存API
- 管理文件
- 自定義存儲
- 基于類的視圖
- 概覽
- 內建顯示視圖
- 內建編輯視圖
- API參考
- 分類索引
- 高級
- 生成 CSV
- 生成 PDF
- 中間件
- 概覽
- 內建的中間件類
- 模板層
- 基礎
- 面向設計師
- 語言概覽
- 人性化
- 面向程序員
- 表單
- 基礎
- 概覽
- 表單API
- 內建的Widget
- 高級
- 整合媒體
- 開發過程
- 設置
- 概覽
- 應用程序
- 異常
- 概覽
- django-admin 和 manage.py
- 添加自定義的命令
- 測試
- 介紹
- 部署
- 概述
- WSGI服務器
- 部署靜態文件
- 通過email追蹤代碼錯誤
- Admin
- 管理操作
- 管理文檔生成器
- 安全
- 安全概述
- 說明Django中的安全問題
- 點擊劫持保護
- 加密簽名
- 國際化和本地化
- 概述
- 本地化WEB UI格式化輸入
- “本地特色”
- 常見的網站應用工具
- 認證
- 概覽
- 使用認證系統
- 密碼管理
- 日志
- 分頁
- 會話
- 數據驗證
- 其它核心功能
- 按需內容處理
- 重定向
- 信號
- 系統檢查框架