20170618-cookie

Cookie

HTTP Cookie, 一般直接叫作cookie,最初是在客戶端用於存儲會話信息的。該標準要求服務器對任意HTTP請求發送Set-Cookie HTTP頭做爲響應的一部分,其中包含會話信息。這個HTTP響應設置一個以name爲名稱、以value爲值的cookie,名稱和值在傳送時都必須是URI編碼的。瀏覽器會存儲這樣的會話信息,並在這以後,經過爲每一個請求添加Cookie HTTP頭將信息發送回服務器,發送回服務器的額外信息能夠用於惟一驗證客戶端來自於發送的哪一個請求。web

Cookie的限制

安全性限制

cookie在性質上是綁定在特定的域名下的。當設定了一個cookie後,再給建立它的域名發送請求時,都會包含這個cookie。這個限制確保了存儲在cookie中的信息只能讓批准的接受者訪問,而沒法被其餘域訪問。瀏覽器

數量限制

  • IE6及更低的版本每一個域名限制爲20個cookie,IE7及之後的版本每一個域名限制爲50個cookie。安全

  • Firefox每一個域名cookie限制爲50個。服務器

  • Opera每一個域名cookie限制爲30個。cookie

  • Safari和Chrome對每一個域的cookie的數量限制沒有硬性規定dom

大小限制

大多數瀏覽器對每一個cookie有大約4096B的長度限制(大約4K)性能

cookie的構成

cookie由瀏覽器保存的如下幾塊信息構成網站

  • 名稱this

  • 編碼

  • 域:cookie對哪一個域是有效的,全部向該域發送的請求中都會包含這個cookie信息,默認值爲設置cookie的那個域

  • 路徑:指定域中的哪一個路徑,應該向服務器發送cookie。例如指定該值爲http://www.example.com/test1/,則只有該路徑下的請求會包含這個cookie

  • 失效時間: cookie什麼時候應該被刪除的時間戳

  • 安全標誌: 指定後,cookie只有在使用SSL鏈接時,纔會發送到服務器

尤爲要注意,域、路徑、失效時間、安全標誌都是服務器給瀏覽器的標識,這些參數並不會做爲發送到服務器的cookie信息的一部分,只有鍵值對纔會被髮送。

JavaScript對cookie的操做

使用document.cookie能夠獲取當前頁面可用的全部的cookie組成的字符串,該字符串是有分號隔開的鍵值對構成(由分號隔開的一個鍵值對就是一個cookie),例如:name1=value1;name2=value2;name3=value3。全部名字和值都是通過URL編碼,因此必須使用decodeURIComponent()來解碼。

document.cookie用於設置值的時候,document.cookie屬性能夠設置爲一個新的字符串,這個cookie字符串會被解釋並添加到現有的cookie集合中。設置document.cookie並不會覆蓋cookie,除非設置的cookie的名稱已經存在

var CookieUtil = {
    get: function(name){
        var cookieName = encodeURIComponent(name) + '=',
            cookieStart = document.cookie.indexOf(cookieName),
            cookieValue = null;
        if(cookieStart > -1){
            cookieEnd = document.cookie.indexOf(';', cookieStart);
            if(cookieEnd == -1){
                cookieEnd = document.cookie.length;
            }
            cookieValue = decodeURIComponent(document.cookie.substring(cookieStart+cookieName.length, cookieEnd));
        }
        return cookieValue;
    },
    
    set: function(name, value, expires, path, domain, secure){
        // 設置的cookie的名稱已存在,將會覆蓋原有的cookie
        var cookieText = encodeURIComponent(name) + '=' + encodeURIComponent(value);
        if(expires instanceof Date){
            cookieText += "; expires=" + expires.toGMTString();
        }
        if(path){
            cookieText += "; path=" + path;
        }
        if(domain){
            cookieText += "; domain=" + domain;
        }
        if(secure){
            cookieText += "; secure=" + secure;
        }
        document.cookie = cookieText;
    },
    // 刪除已有cookie
    unset: function(name, path, domain, secure){
        this.set(name, "", new Date(), path, domain, secure);
    }
}

子cookie

爲了繞開瀏覽器的單域名下的cookie數量限制,能夠在每一個cookie中存放多個更小的字段(子cookie)。子cookie最多見的格式以下:

'name=name1=value1&name2=value2&name3=value3'

子cookie通常也以查詢字符串的格式進行格式化。而後這些值可使用單個cookie進行存儲和訪問,而非對每一個鍵值對使用不一樣的cookie存儲。最後網站或web應用程序能夠無需達到單域名cookie上限也能夠存儲更加結構化的數據。爲了更好地操做子cookie,必須創建一系列新方法。子cookie的解析和序列化會因子cookie的指望用途而略有不一樣並更加複雜些。

var SubCookieUtil = {
    get: function(name, subName){
        var subCookies = this.getAll(name)
        if(subCookies){
            return subCookies[subName];
        } else {
            return null;
        }
    },
    
    getAll: function(name){
        var cookieName = encodeURIComponent(name) + "=",
            cookieStart = document.cookie.indexOf(cookieName),
            cookieValue = null,
            cookieEnd,
            subCookie,
            i,
            parts,
            result = {};
        
        if(cookeStart > -1){
            cookieEnd = document.cookie.indexOf(";", cookieStart);
            if(cookieEnd == -1){
                cookieEnd = document.cookie.length;
            }
            cookieValue = document.cookie.substring(cookieStart+cookieName.length, cookieEnd);
            if(cookieValue.length>0){
                subCookies = cookieValue.split("&");
                
                for(i=0, len=subCookies.length; i<len;i++){
                    parts = subCookies[i].split("=");
                    result[decodeURIComponent(parts[0])] = decodeURIComponent(parts[1]);
                }
                return result;
            }
        }
        return null;
    },
    
    set: function(name, subName, value, expires, path, domain, secure){
        var subcookies = this.getAll(name)||{};
        subcookies[subName] = value;
        this.setAll(name, subcookies, expires, path, domain, secure);
    },
    
    setAll: function(name, subcookies, expires, path, domain, secure){
        var cookieText = encodeURIComponent(name) + "=",
            subcookieParts = new Array(),
            subName;
        
        for(subName in subcookies){
            if(subName.length >0 && subcookies.hasOwnProperty(subName)){
                subcookieParts.push(encodeURIComponent(subName) + "=" +
                    encodeURIComponent(subcookies[subName]);
            }
        }
        
        if(cookieParts.length >0){
            cookieText += subcookieParts.join("&");
            if(expires instanceof Date){
                cookieText += "; expires=" + expires.toGMTSting();
            }
            if(path){
                cookieText += "; path=" + path;
            }
            if(domain){
                cookieText += "; domain=" + domain;
            }
            if(secure){
                cookieText += "; secure=" + secure;
            }
        } else {
            cookieText += "; expires="+(newDate(0)).toGMTString();
        }
        document.cookie = cookieText;
    },
    
    unset: function(name, subName, path, domain, secure){
        var subcookies = this.getAll(name);
        if(subcookies){
            delete subcookies[subName];
            this.set(name, subcookies, null, path, domain, secure);
        }
    },
    
    unsetAll: function(name, path, domain, secure){
        this.setAll(name, null, new Date(0), path, domain, secure);
    }
};

關於cookie的思考

  • 操做cookie的時候須要密切關注cookie的長度,以防超過單個cookie的長度限制

  • 全部的cookie都會由瀏覽器做爲請求內容的一部分發送,因此在cookie中存儲大量信息會影響到特定域的請求性能。cookie越大,完成對服務器請求的時間就越長。儘管瀏覽器對cookie進行了大小限制,不過最好仍是儘量在cookie中少存儲信息,以免影響性能。

  • cookie的性質和侷限性使其並不能做爲存儲大量信息的理想手段。

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息