# 第七章:cookie和session
# cookie和session
1. cookie:在網站中,http請求是無狀態的。也就是說即使第一次和服務器連接后并且登錄成功后,第二次請求服務器依然不能知道當前請求是哪個用戶。`cookie`的出現就是為了解決這個問題,第一次登錄后服務器返回一些數據(cookie)給瀏覽器,然后瀏覽器保存在本地,當該用戶發送第二次請求的時候,就會自動的把上次請求存儲的`cookie`數據自動的攜帶給服務器,服務器通過瀏覽器攜帶的數據就能判斷當前用戶是哪個了。`cookie`存儲的數據量有限,不同的瀏覽器有不同的存儲大小,但一般不超過4KB。因此使用`cookie`只能存儲一些小量的數據。
2. session: session和cookie的作用有點類似,都是為了存儲用戶相關的信息。不同的是,`cookie`是存儲在本地瀏覽器,`session`是一個思路、一個概念、一個服務器存儲授權信息的解決方案,不同的服務器,不同的框架,不同的語言有不同的實現。雖然實現不一樣,但是他們的目的都是服務器為了方便存儲數據的。`session`的出現,是為了解決`cookie`存儲數據不安全的問題的。
3. cookie和session使用:`web`開發發展至今,`cookie`和`session`的使用已經出現了一些非常成熟的方案。在如今的市場或者企業里,一般有兩種存儲方式:
- 存儲在服務端:通過`cookie`存儲一個`sessionid`,然后具體的數據則是保存在`session`中。如果用戶已經登錄,則服務器會在`cookie`中保存一個`sessionid`,下次再次請求的時候,會把該`sessionid`攜帶上來,服務器根據`sessionid`在`session`庫中獲取用戶的`session`數據。就能知道該用戶到底是誰,以及之前保存的一些狀態信息。這種專業術語叫做`server side session`。`Django`把`session`信息默認存儲到數據庫中,當然也可以存儲到其他地方,比如緩存中,文件系統中等。存儲在服務器的數據會更加的安全,不容易被竊取。但存儲在服務器也有一定的弊端,就是會占用服務器的資源,但現在服務器已經發展至今,一些`session`信息還是綽綽有余的。
- 將`session`數據加密,然后存儲在`cookie`中。這種專業術語叫做`client side session`。`flask`框架默認采用的就是這種方式,但是也可以替換成其他形式。
## 在django中操作cookie和session:
### 操作cookie:
#### 設置cookie:
設置`cookie`是設置值給瀏覽器的。因此我們需要通過`response`的對象來設置,設置`cookie`可以通過`response.set_cookie`來設置,這個方法的相關參數如下:
1. `key`:這個`cookie`的`key`。
2. `value`:這個`cookie`的`value`。
3. `max_age`:最長的生命周期。單位是秒。
4. `expires`:過期時間。跟`max_age`是類似的,只不過這個參數需要傳遞一個具體的日期,比如`datetime`或者是符合日期格式的字符串。如果同時設置了`expires`和`max_age`,那么將會使用`expires`的值作為過期時間。
5. `path`:對域名下哪個路徑有效。默認是對域名下所有路徑都有效。
6. `domain`:針對哪個域名有效。默認是針對主域名下都有效,如果只要針對某個子域名才有效,那么可以設置這個屬性.
7. `secure`:是否是安全的,如果設置為`True`,那么只能在`https`協議下才可用。
8. `httponly`:默認是`False`。如果為`True`,那么在客戶端不能通過`JavaScript`進行操作。
#### 刪除cookie:
通過`delete_cookie`即可刪除`cookie`。實際上刪除`cookie`就是將指定的`cookie`的值設置為空的字符串,然后使用將他的過期時間設置為`0`,也就是瀏覽器關閉后就過期。
#### 獲取cookie:
獲取瀏覽器發送過來的`cookie`信息。可以通過`request.COOKIES`來或者。這個對象是一個字典類型。比如獲取所有的`cookie`,那么示例代碼如下:
```
<pre class="calibre12">```
cookies = request.COOKIES
<span class="hljs-keyword">for</span> cookie_key,cookie_value <span class="hljs-keyword">in</span> cookies.items():
print(cookie_key,cookie_value)
```
```
- - - - - -
### 操作session:
`django`中的`session`默認情況下是存儲在服務器的數據庫中的,在表中會根據`sessionid`來提取指定的`session`數據,然后再把這個`sessionid`放到`cookie`中發送給瀏覽器存儲,瀏覽器下次在向服務器發送請求的時候會自動的把所有`cookie`信息都發送給服務器,服務器再從`cookie`中獲取`sessionid`,然后再從數據庫中獲取`session`數據。但是我們在操作`session`的時候,這些細節壓根就不用管。我們只需要通過`request.session`即可操作。示例代碼如下:
```
<pre class="calibre12">```
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">index</span><span class="hljs-params">(request)</span>:</span>
request.session.get(<span class="hljs-string">'username'</span>)
<span class="hljs-keyword">return</span> HttpResponse(<span class="hljs-string">'index'</span>)
```
```
`session`常用的方法如下:
1. `get`:用來從`session`中獲取指定值。
2. `pop`:從`session`中刪除一個值。
3. `keys`:從`session`中獲取所有的鍵。
4. `items`:從`session`中獲取所有的值。
5. `clear`:清除當前這個用戶的`session`數據。
6. `flush`:刪除`session`并且刪除在瀏覽器中存儲的`session_id`,一般在注銷的時候用得比較多。
7. `set_expiry(value)`:設置過期時間。
- 整形:代表秒數,表示多少秒后過期。
- `0`:代表只要瀏覽器關閉,`session`就會過期。
- `None`:會使用全局的`session`配置。在`settings.py`中可以設置`SESSION_COOKIE_AGE`來配置全局的過期時間。默認是`1209600`秒,也就是2周的時間。
8. `clear_expired`:清除過期的`session`。`Django`并不會清除過期的`session`,需要定期手動的清理,或者是在終端,使用命令行`python manage.py clearsessions`來清除過期的`session`。
### 修改session的存儲機制:
默認情況下,`session`數據是存儲到數據庫中的。當然也可以將`session`數據存儲到其他地方。可以通過設置`SESSION_ENGINE`來更改`session`的存儲位置,這個可以配置為以下幾種方案:
1. `django.contrib.sessions.backends.db`:使用數據庫。默認就是這種方案。
2. `django.contrib.sessions.backends.file`:使用文件來存儲session。
3. `django.contrib.sessions.backends.cache`:使用緩存來存儲session。想要將數據存儲到緩存中,前提是你必須要在`settings.py`中配置好`CACHES`,并且是需要使用`Memcached`,而不能使用純內存作為緩存。
4. `django.contrib.sessions.backends.cached_db`:在存儲數據的時候,會將數據先存到緩存中,再存到數據庫中。這樣就可以保證萬一緩存系統出現問題,session數據也不會丟失。在獲取數據的時候,會先從緩存中獲取,如果緩存中沒有,那么就會從數據庫中獲取。
5. `django.contrib.sessions.backends.signed_cookies`:將`session`信息加密后存儲到瀏覽器的`cookie`中。這種方式要注意安全,建議設置`SESSION_COOKIE_HTTPONLY=True`,那么在瀏覽器中不能通過`js`來操作`session`數據,并且還需要對`settings.py`中的`SECRET_KEY`進行保密,因為一旦別人知道這個`SECRET_KEY`,那么就可以進行解密。另外還有就是在`cookie`中,存儲的數據不能超過`4k`。
- Introduction
- 第一章:學前準備
- 第一節:虛擬環境
- 第二節:準備工作
- 第三節:Django介紹
- 第四節:URL組成部分
- 第二章:URL與視圖
- 第一節:第一個Django項目
- 第二節:視圖與URL分發器
- 第三章:模板
- 第一節:模板介紹
- 第二節:模板變量
- 第三節:常用標簽
- 第四節:常用過濾器
- 第五節:自定義過濾器
- 第七節:模版結構優化
- 第八節:加載靜態文件
- 第四章:數據庫
- 第一節:MySQL相關軟件
- 第二節:數據庫操作
- 第三節:ORM模型
- 第四節:模型常用字段
- 第五節:外鍵和表關系
- 第六節:增刪改查操作
- 第七節:查詢操作
- 第八節:QuerySet API
- 第九節:ORM模型遷移
- 第十節:ORM作業
- 第十一節:ORM作業參考答案
- 第十二節:Pycharm連接數據庫
- 第五章:視圖高級
- 第一節:限制請求method
- 第二節:頁面重定向
- 第三節:HttpRequest對象
- 第四節:HttpResponse對象
- 第五節:生成CSV文件
- 第六節:類視圖
- 第七節:錯誤處理
- 第六章:表單
- 第一節:表單概述
- 第二節:用表單驗證數據
- 第三節:ModelForm
- 第四節:文件上傳
- 第七章:cookie和session
- 第八章:上下文處理器和中間件
- 第一節:上下文處理器
- 第二節:中間件
- 第九章:安全
- 第一節:CSRF攻擊
- 第二節:XSS攻擊
- 第三節:點擊劫持攻擊
- 第四節:SQL注入
- 第十章:信號
- 第一節:什么是信號
- 第十一章:驗證和授權
- 第一節:概述
- 第二節:用戶對象
- 第三節:權限和分組
- 第十二章:Admin系統
- 第十三章:Django的緩存
- 第十四章:memcached
- 第十五章:Redis