cookie定義及組成
對於Cookie的定義,跟語言沒有關係的,不管Server端用的是Java、Python等後端語言哪一種,涉及到web開發相關知識時候,必須瞭解這方面知識。
定義
Cookie 並不是它的原意“甜餅”的意思, 而是一個保存在客戶機中的簡單的文本文件, 這個文件與特定的 Web 文檔關聯在一起, 保存了該客戶機訪問這個Web 文檔時的信息, 當客戶機再次訪問這個 Web 文檔時這些信息可供該文檔使用。由於“Cookie”具有可以保存在客戶機上的神奇特性, 因此它可以幫助我們實現記錄用戶個人信息的功能, 而這一切都不必使用複雜的CGI等程序 [2] 。
舉例來說, 一個 Web 站點可能會爲每一個訪問者產生一個唯一的ID, 然後以 Cookie 文件的形式保存在每個用戶的機器上。如果使用瀏覽器訪問 Web, 會看到所有保存在硬盤上的 Cookie。在這個文件夾裏每一個文件都是一個由“名/值”對組成的文本文件,另外還有一個文件保存有所有對應的 Web 站點的信息。在這裏的每個 Cookie 文件都是一個簡單而又普通的文本文件。透過文件名, 就可以看到是哪個 Web 站點在機器上放置了Cookie(當然站點信息在文件裏也有保存)
組成:
Cookie是一段不超過4KB的小型文本數據,由一個名稱(Name)、一個值(Value)和其它幾個用於控制Cookie有效期、安全性、使用範圍的可選屬性組成。其中 [3] :
(1)Name/Value:設置Cookie的名稱及相對應的值,對於認證Cookie,Value值包括Web服務器所提供的訪問令牌 [3] 。
(2)Expires屬性:設置Cookie的生存期。有兩種存儲類型的Cookie:會話性與持久性。Expires屬性缺省時,爲會話性Cookie,僅保存在客戶端內存中,並在用戶關閉瀏覽器時失效;持久性Cookie會保存在用戶的硬盤中,直至生存期到或用戶直接在網頁中單擊“註銷”等按鈕結束會話時纔會失效 [3] 。
(3)Path屬性:定義了Web站點上可以訪問該Cookie的目錄 [3] 。
(4)Domain屬性:指定了可以訪問該 Cookie 的 Web 站點或域。Cookie 機制並未遵循嚴格的同源策略,允許一個子域可以設置或獲取其父域的 Cookie。當需要實現單點登錄方案時,Cookie 的上述特性非常有用,然而也增加了 Cookie受攻擊的危險,比如攻擊者可以藉此發動會話定置攻擊。因而,瀏覽器禁止在 Domain 屬性中設置.org、.com 等通用頂級域名、以及在國家及地區頂級域下注冊的二級域名,以減小攻擊發生的範圍 [3] 。
(5)Secure屬性:指定是否使用HTTPS安全協議發送Cookie。使用HTTPS安全協議,可以保護Cookie在瀏覽器和Web服務器間的傳輸過程中不被竊取和篡改。該方法也可用於Web站點的身份鑑別,即在HTTPS的連接建立階段,瀏覽器會檢查Web網站的SSL證書的有效性。但是基於兼容性的原因(比如有些網站使用自簽署的證書)在檢測到SSL證書無效時,瀏覽器並不會立即終止用戶的連接請求,而是顯示安全風險信息,用戶仍可以選擇繼續訪問該站點。由於許多用戶缺乏安全意識,因而仍可能連接到Pharming攻擊所僞造的網站 [3] 。
(6)HTTPOnly 屬性 :用於防止客戶端腳本通過document.cookie屬性訪問Cookie,有助於保護Cookie不被跨站腳本攻擊竊取或篡改。但是,HTTPOnly的應用仍存在侷限性,一些瀏覽器可以阻止客戶端腳本對Cookie的讀操作,但允許寫操作;此外大多數瀏覽器仍允許通過XMLHTTP對象讀取HTTP響應中的Set-Cookie頭
應用
從定義上來理解cookie,可以作爲存儲介質,存儲一些必要的信息在客戶端,當然這些重要的信息是在第一次在服務端設置到cookie裏面,當第二次訪問請求的時候,服務端通過cookie裏面的值來判定是否有一些必要的數據,從而減輕了Server端的訪問壓力,也就是通過cookie來做了驗證的操作。
舉例說明:
模擬用戶登錄進入首頁的操作:cookie裏面存儲用戶username
- 用戶進入首頁操作,通過cookie來判斷,如果用戶cookie已經存在username,就直接跳轉到index頁面,如果不存在就直接跳轉到login登錄界面
- 登錄界面的操作,在登錄成功後,存儲username值到cookie裏面,用於下次直接訪問首頁index時判斷是否已經登錄了
view中的邏輯代碼如下:
user_info = {
'test': {'pwd': "123123"},
}
def login(request):
if request.method == "GET":
return render(request, 'cookie_login.html')
if request.method == "POST":
u = request.POST.get('username')
p = request.POST.get('pwd')
dic = user_info.get(u)
if not dic:
return render(request, 'cookie_login.html')
if dic['pwd'] == p:
res = redirect('/cookietest/index/')
res.set_cookie('username', u) # 給重定向的url設cookie
return res
else:
return render(request, 'cookie_login.html')
def index(reqeust):
v = reqeust.COOKIES.get('username') # 獲取當前已經登錄的用戶
if not v: # 如果獲取不到cookie表示沒有登錄
return redirect('/cookietest/login/')
return render(reqeust, 'cookie_test_index.html', {'current_user': v})
login和index頁面分別如下:
cookie_login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>cookie_test_login</title>
</head>
<body>
<form action="/cookietest/login/" method="POST">
<input type="text" name="username" placeholder="用戶名"/>
<input type="password" name="pwd" placeholder="密碼"/>
<input type="submit"/>
</form>
</body>
</html>
cookie_test_index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Cookie_test_index</title>
</head>
<body>
<h1>歡迎登錄:{{ current_user }}</h1>
</body>
</html>
登錄到進入首頁後,看一下瀏覽器中的cookie有哪些值:
把👆demo跑起來,實際調試下瀏覽器,初步理解cookie是做什麼。
Cookie 相關api
設置cookie 都是response.py裏面的方法,比如上面用的就是第一種:res.set_cookie(‘username’, u)
- 第一種:def set_cookie()
- 第二種:def set_signed_cookie
HttpResponse(...) 或 rep = render(request, ...)
rep.set_cookie(key,value,...)
rep.set_signed_cookie(key,value,salt='加密鹽',...)
參數:
key, 鍵
value='', 值
max_age=None, 超時時間
expires=None, 超時時間(IE requires expires, so set it if hasn't been already.)
path='/', Cookie生效的路徑,/ 表示根路徑,特殊的:跟路徑的cookie可以被任何url的頁面訪問
domain=None, Cookie生效的域名
secure=False, https傳輸
httponly=False 只能http協議傳輸,無法被JavaScript獲取(不是絕對,底層抓包可以獲取到也可以被覆蓋)
取cookie
也有兩種方法,其實針對不同的設置對應不同的獲取方法,對於第二種加鹽處理的算法,django已經爲我們做了。
request.COOKIES['key']
request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)
參數:
default: 默認值
salt: 加密鹽
max_age: 後臺控制過期時間
上面的demo我們就是這樣獲取的:
v = reqeust.COOKIES.get('username')
分析流程
有沒有發現👆的獲取cookie和設置cookie是怎樣的操作流程:
- response裏面設置cookie,返回到客戶端【瀏覽器】
- 通過request來獲取cookie
- cookie其實是存在客戶端【瀏覽器裏面的】
所以我們是不是可以得到以下結論: - 在請求和響應的過程中,cookie其實就是在請求頭裏面的,所以Server端能夠設置和獲取
- 既然在客戶端,那麼這個cookie其實也是可以在客戶端進行重寫的
優缺點
優點:
- http請求的無記憶性;
- 加快訪問速度
- 減少服務器壓力
缺點
- 大小限制了,太小
- 安全因素太低,一般通過加密和session共同使用
- 客戶端可能禁用cookie,導致cookie不可用
特點
- cookies保存在客戶端瀏覽器上的鍵值對,且每次訪問頁面都會帶着cookies
- cookies可以主動清除
- cookies也可以被"僞造",可以被別人帶着cookies操作你的賬號
- cookies會根據域名進行分類,不能跨域共享,也就是說百度有百度的,JD有京東的
- cookies必須請求數據成功後纔能有用哈
- 瀏覽器可以設置不接收Cookies
- 服務器端設置的cookies
- cookies可以設置超時時間, max_age=10