cookie與session的實現原理

HTTP被設計為”無狀態”,每次請求都處於相同的空間中。 在一次請求和下一次請求之間沒有任何狀態保持,我們無法根據請求的任何方面(IP地址,用戶代理等)來識別來自同一人的連續請求。上圖很明顯的展示了Django的session與cookie的實現原理。服務器會生成兩份相同的cookie字符串,一份保存在本地,一份發向請求的瀏覽器。瀏覽器將收到的cookie字符串保存下來,當下次再發請求時,會將信息與這段cookie一同發送到服務器,服務器得到這段cookie會與本地保存的那份判斷是否相同,如果相同就表示用戶已經登錄成功,保存用戶登錄成功的狀態。Django的session保存在數據庫中的數據相當於一個大字典,key為cookie的字符串,value仍是一個字典,字典的key和value為用戶設置的相關信息。這樣就可以方便的存取session里面的信息。
Cookies
cookies 是瀏覽器為 Web 服務器存儲的一小段信息。 每次瀏覽器從某個服務器請求頁面時,它向服務器回送之前收到的cookies。它保存在瀏覽器下的某個文件夾下。
瀏覽器下的cookie:

Session
Django的Session機制會向請求的瀏覽器發送cookie字符串。同時也會保存到本地一份,用來驗證瀏覽器登錄是否為同一用戶。它存在於服務器,Django默認會把session存入到數據庫中。
Session依賴於Cookie,如果瀏覽器不能保存cooki那么session就失效了。因為它需要瀏覽器的cooki值去session里做對比。session就是用來在服務器端保存用戶的會話狀態。
操作session
根據網友lvusyy的友情提示,在操作session之前,你需要同步一下Django的數據庫。我用的是Django自帶的sqlite3.所以需要執行同步的命令:


還有一點,在django處理請求的過程中,需要經過中間件的過濾,涉及到跨站請求偽造時,django會把請求阻止過濾掉,所以我們要在setting.py中禁用跨站請求偽造的中間件,如果不禁用,記得好像會報一個403的錯誤黃頁。關於跨站請求偽造,之后的章節我會詳細說明其功能用處:

Django中操作session:
獲取session:request.session[key] request.session.get(key)
設置session:reqeust.session[key] = value
刪除session:del request[key]
request.session是每一個客戶端相當於在上圖中對應的value
一段簡單的Django中實現session的代碼,判斷用戶是否已經成功登錄:
1 def login(request): 2 if request.method =='POST': 3 username = request.POST.get('username') 4 pwd = request.POST.get('pwd') 5 if username =='lisi' and pwd == '12345': 6 request.session['IS_LOGIN'] = True 設置session 7 return redirect('/app01/home/') 8 9 return render(request,'login.html') 10 11 def home(request): 12 is_login = request.session.get('IS_LOGIN',False) 獲取session里的值 13 if is_login: 14 return HttpResponse('order') 15 else: 16 return redirect('/app01/login/')
過期時間
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_COOKIE_AGE:設置cookie在瀏覽器中存活的時間
在settings.py中添加:

例子
結合前端實現的cookie與session會話機制:
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <title></title>
6 </head>
7 <body>
8 <form action="/app01/login/" method="post">
9 <input type="text" name="username" />
10 <input type="password" name="pwd" />
11 <input type="submit" value="submit"/>
12 </form>
13
14 </body>
15 </html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style> .header{ height: 48px;
}
</style>
</head>
<body>
<div class="header">
<div style="float: right">{{ username }}</div>
<div style="float: right"><a href="/app01/logout/">注銷</a></div>
</div>
<div style="height: 500px;background-color: #ddd"></div>
</body>
</html>
views.py
def login(request): if request.method == "POST": username = request.POST.get('username') pwd = request.POST.get('pwd') if username == 'alex' and pwd == '123': request.session['IS_LOGIN'] = True request.session['USRNAME'] = 'alex'
return redirect('/app01/home/') elif username == 'eirc' and pwd == '123': request.session['IS_LOGIN'] = True request.session['USRNAME'] = 'eirc'
return redirect('/app01/home/') return render(request, 'login.html') def home(request): is_login = request.session.get('IS_LOGIN', False) if is_login: username = request.session.get('USRNAME', False) return render(request, 'home.html', {'username': username}) else: return redirect("/app01/login/")

