客户端与服务器cookie
認識cookie
第一部分: 概要
cookie是一種早期使用的客戶端存儲機制(現在仍在廣泛使用),cookie數據會在Web瀏覽器和Web服務器之間傳輸, 因為早期cookie是針對服務器腳本設計的,所以服務端腳本可以讀、寫存儲在客戶端的cookie的值。 值得注意的是, 任何以cookie形式存儲的值,無論服務器端是否需要,每一個HTTP請求都會把這些數據(cookie數據)傳輸到服務器端。但是cookie的存儲量較小,一般不得超過4kb,即4096個字節。由于存儲能力較弱,現在比較流行的是WebStorage,
Cookie是訪問過的網站創建的文件,用于存儲瀏覽器信息,例如個人資料。
cookie的缺點:
- 數據存儲大小:4kb,作為數據存儲容器,卻只有4kb,對于目前稍微有一些繁雜的頁面,cookie就不夠用了。
- 安全性問題: cookie是在HTTP中明文傳遞的(HTTPs不是,這和協議有關,與cookie本身無關),所以說這是非常不安全的。
- 網絡負擔: 之前提到cookie會隨著HTTP請求在web瀏覽器和服務器間傳遞,這是非常浪費帶寬的。
HTTP Cookie,通常直接叫做cookie,標準要求服務器將Set-Cookie作為響應的一部分,其中包含會話信息,這種服務器響應報文的首部字段可能如下,其中以name為名稱、以value為值,這是要求客戶端發送name這個鍵名的cookie值,如下:
HTTP/1.1 200 OK Content-type: Text/html Set-Cookie: name=value Other-header: other-header-value那么瀏覽器端的請求就是這樣的:
GET /index.html HTTP/1.1 Cookie: name=value Other-header: other-header-value即把服務器需要的name的值發送到服務器端。
將cookie發送到服務器可以使得服務器知道關于此用戶的更多信息。
? 注意: 每一個cookie的格式都是這樣的: <cookie名> = <值>; 名稱和值都必須是合法的標識符。
? 注意: cookie是存在有效期的, 在默認情況下,cookie的聲明周期就是在瀏覽器關閉的時候結束,如果想要使得cookie在瀏覽器關閉之后還可以用,就要為cookie設置有效期,也就是cookie的實效日期。
補充: 上面的cookie有效期說法是有問題的,不是說瀏覽器關閉的時候結束。 比如mail.qq.com這個網站,當我們輸入密碼登錄之后,即使關閉了這個瀏覽器,然后在另外一個一直存在chrome瀏覽器中再打開mail.qq.com,發現還是可以直接使用而無需登錄的。 但是呢,如果再我們登錄之后,一下關閉掉所有的chrome瀏覽器,然后再打開,就發現,確實需要重新輸入了,這便是一個cookie的生存周期。 下面進行驗證:
?我們打開chrome瀏覽器,最開始一般就是一個空的標簽頁,然后去看與chrome有關的進程數,可以看到最開始有10個左右,
? ? 然后我們在打開幾個標簽頁,如下所示:
然后再去看chrome的進程數,可以發現現在大約是15到16個,接下來,我們把這些標簽頁分開,如下所示:
? ? ? ?
然后再去看進程數,發現并沒有變化,所以說,瀏覽器的生命周期不是說創建一個新的窗口就是一個新的生命周期,而是所有的標簽,一旦所有的chrome瀏覽器的標簽都關閉了,那么chrome的生命周期也就結束了。
?
?
?
?
?
?
?
?
?
第二部分:cookie查看
我們可以使用 console.log(window.navigator.cookieEnabled)?查看我們自己瀏覽器的cookie功能是否打開,它返回一個布爾值,如果為true就說明打開了。?
如果打開chrome的內容設置中的“阻止網站設置任何數據”這樣我們使用上面的代碼,就可以發現cookie功能關閉了,即false。這時,客戶端就不會再存儲任何cookie了。
實際上cookie就是一些字符串信息,這些信息放在客戶端的計算機上,用于客戶端計算機和服務器之間傳遞信息。我們可以使用 alert(typeof document.cookie) 來檢測
在JavaScript中可以通過 document.cookie 來讀取或設置這些信息,由于cookie 多用在客戶端和服務器之間傳遞信息,所以除了JavaScript之外,服務器端的語言如PHP也可以存取cookie。
? 由于cookie最終都是以文件形式存放在客戶端,所以查看和修改cookie都是十分方便的,這就是為什么常說cookie不能存放重要信息的原因。
有時候,在服務器發送set-Cookie字段時,即要求瀏覽器攜帶上某些cookie,以便下次再請求的時候可以防止再次登錄等。除了key-value,還可以在服務器端設置好 httponly,這樣,用戶就不能通過 document.cookie 進行xss攻擊了。
?
?
第三部分: 關于cookie的一些限制?
cookie有 域和路徑 這個概念。域就是domin 的概念,因為瀏覽器是一個主意安全的環境,所以不能域之間必然是不能互相訪問cookie的(當然可以通過跨域的方式做到就向jsonp),路徑就是routing的概念,一個網頁所創建的cookie只能被與這個網頁在同一目錄或子目錄下的網頁訪問,而不能被其他目錄下的網頁訪問。
?
?
?
第四部分: Cookie常見問題
cookie存在兩種類型
- 你瀏覽的當前網站設置的cookie。
- 來自網頁上嵌入廣告或圖片等其他域來源的第三方cookie(網站通過使用這些cookie可以跟蹤你的使用信息)
Cookie的聲明周期大致可以分為兩種狀態:
- 其一: 即臨時性質的cookie, 當前使用的過程中網站會儲存一些你的個人信息,后面就用不到了,所以瀏覽器關閉之后這些信息就從計算機中刪除。
- 其二: 設置了失效時間的cookie,比如你的用戶名和密碼通過cookie李記錄,這樣就不需要每次都自己輸入后登陸而是直接登陸了。 可以設置保留幾天、幾十天等。
Cookie的兩種清除方式
- 瀏覽器自身的設置中清除
- 通過設置cookie的有效期
- 說明: 刪除cookie有可能導致某些網頁無法正常運行(如:我將cookie功能關閉,現在寫的博文就不能正常提交)
瀏覽器可以通過設置接受或拒絕訪問cookie,處于性能和功能的考慮,盡量降低cookie的使用數量。
假如是本地磁盤中的頁面,chrome的控制臺是無法用JavaScript讀寫操作 cookie 的,解決辦法...換一個瀏覽器^_^。
?
?
第五部分: cookie基礎用法
一、 簡單的存取操作
使用js存取cookie時,必須使用document的cookie屬性,如下:
document.cookie = 'username=zzw';
?注意: 其中username就是cookie的名稱,zzw就是這個名稱對應的值。?假設 cookie 名稱并不存在,那么就是創建一個新的 cookie;如果存在就是修改了這個 cookie 名稱對應的值。如果要多次創建 cookie ,重復使用這個方法即可。
我們還可以通過document.cookie.length來查看有多少對這樣的cookie。
?
二、 cookie的讀取操作
下面的代碼是w3school上的例子
function getCookie(c_name){if (document.cookie.length>0){ //先查詢cookie是否為空,為空就return ""c_start=document.cookie.indexOf(c_name + "=") //通過String對象的indexOf()來檢查這個cookie是否存在,不存在就為 -1 if (c_start!=-1){ c_start=c_start + c_name.length+1 //最后這個+1其實就是表示"="號啦,這樣就獲取到了cookie值的開始位置c_end=document.cookie.indexOf(";",c_start) //其實我剛看見indexOf()第二個參數的時候猛然有點暈,后來想起來表示指定的開始索引的位置...這句是為了得到值的結束位置。因為需要考慮是否是最后一項,所以通過";"號是否存在來判斷if (c_end==-1) c_end=document.cookie.length return unescape(document.cookie.substring(c_start,c_end)) //通過substring()得到了值。想了解unescape()得先知道escape()是做什么的,都是很重要的基礎,想了解的可以搜索下,在文章結尾處也會進行講解cookie編碼細節 } }return ""}可以看得出來,這實際上就是對字符串進行操作。
?
?
三、設置cookie的有效期
默認情況,cookie在瀏覽器關閉就實效了,但是我們可以通過下面的方式來設置有效期:
document.cookie = "name=value;expires=date"
顯然,這里的name=value是一個個的cookie對,而expires這個key是一個關鍵詞,可以被唯一的識別出來,而不能作為一般的cookie來傳遞。
?
上面的data值為GMT時間(格林威治時間)的日期型字符串,生成方式如下:
var _date = new Date();
_date.setDate(_date.getDate()+30);
_data.toGMTString();
直接在本機上運行,結果是:"Fri, 21 Apr 2017 19:21:11 GMT"
我們通過 +30 就可以設置cookie的有效時間是30天了。注意:setDate和getDate的使用。
?
?
第六部分: Cookie路徑概念
默認情況下,只有與創建 cookie 的頁面在同一個目錄或子目錄下的網頁才可以訪問,這個是因為安全方面的考慮,造成不是所有頁面都可以隨意訪問其他頁面創建的 cookie。
如:在 "http://www.cnblogs.com/Darren_code/" 這個頁面創建一個cookie,那么在"/Darren_code/"這個路徑下的頁面如: "http://www.cnblogs.com/Darren_code/archive/2011/11/07/Cookie.html"這個頁面默認就能取到cookie信息,因為這個頁面時上面的路徑的子目錄下的頁面。而因為"http://www.cnblogs.com"或者 "http://www.cnblogs.com/xxxx/"不是在同一個目錄下,所以不能訪問cookie了。
?
?
第七部分: Cookie安全性
之前說到,cookie在報文和本地文件中,都可以看到,所以不能存放重要的信息,他們都是不安全的。但是cookie中傳遞的內容非常重要,就要用加密的方式來傳輸數據。?
即如果把cookie的屬性名稱為secure,默認的值為空,那么它和服務器之間就會通過https或其他的安全協議傳輸數據,如下:
document.cookie = "username=zzw;secure"
?值得注意的是: 這樣只能保證cookie和服務器之間的數據傳輸是加密的,但是本地文件依舊沒有加密。所以本地的cookie還是很容易看到的。
?
?
第八部分: cookie編碼細節
在輸入cookie信息時不能包含空格、分號、逗號等特殊符號。 而在一般情況下,cookie都是采用未編碼的方式。 所以,在設置cookie之前應當使用escape()函數先將cookie進行編碼,在獲取到cookie的時候使用unescapse()函數把值進行轉換回來。
?
?
?
第九部分: cookie獲取
注意: 如果我們直接在本地創建一個html,那么通過document.cookie是不能進行設置和獲取的,而必須在http的網頁下才可以,就像我們測試跨域一樣,在本地無法測試,而是只能在node服務器環境下進行測試。主要函數如下所示:
var myCookie = 'name=wayne;girfriend=hedy;object=marry;appearence=handsome;future=promising;children=11';function getCookie(myCookie, key) {if (typeof key != 'string' || typeof document.cookie != 'string') {console.error('輸入參數格式錯誤!');return;} else if (key == '') {console.error('key不能為空!');return;}if (myCookie.length == 0) {console.error('cookie為空!');return;}var cookieArr = myCookie.split(';'),temp;for (var i = 0, len = cookieArr.length; i < len; i++) {temp = cookieArr[i].split('=');// 這里需要進行trim處理,否則會出現問題,因為cookie的key之前會添加空格。if (temp[0].trim() == key) {console.log(temp[1]);return;}}console.error(key + '不存在!');return;}getCookie(myCookie, 'name');其中在函數內部的前面,我做了很多判斷,因為輸入可能是有問題的,對于全局異常處理要有很好的把控。
?
另外,這個函數也是可以直接在網站下使用的,如下:
?
?
?
?
?
?
?
?
?
參考文章:http://www.cnblogs.com/Darren_code/archive/2011/11/24/Cookie.html
http://www.cnblogs.com/xiaohuochai/p/6591392.html
轉載于:https://www.cnblogs.com/zhuzhenwei918/p/6603151.html
總結
以上是生活随笔為你收集整理的客户端与服务器cookie的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ESP8266 问题
- 下一篇: Windows 中 SQLite3 使用