客戶端存儲技術總結

客戶端存儲方式web

 

  1. COOKIE

由NetScape公司創造,指保存在用戶本地終端內存或磁盤上的一小塊數據,只能保存字符串類型,全部的cookie信息都會隨着瀏覽器的請求而發送。儘管幾乎全部瀏覽器都支持cookie,但容量小是它最致命的缺點,單域cookie數量不該超過20個,總長度不該超過4K,對於如今web應用本地存儲數據量的需求是遠遠不夠的,並且因爲它是明文傳輸,禁止在cookie中保存如電話號碼,帳號密碼等敏感信息。chrome

 

1.1 Cookie機制數據庫

Web應用程序是使用HTTP協議傳輸數據的。HTTP協議是無狀態的協議。一旦數據交換完畢,客戶端與服務器端的鏈接就會關閉,再次交換數據須要創建新的鏈接。這就意味着服務器沒法從鏈接上跟蹤會話。Cookie就是這樣的一種機制。它能夠彌補HTTP協議無狀態的不足。在Session出現以前,基本上全部的網站都採用Cookie來跟蹤會話。跨域

 

1.2 什麼是Cookie瀏覽器

Cookie其實是一小段的文本信息。客戶端請求服務器,若是服務器須要記錄該用戶狀態,就使用response向客戶端瀏覽器頒發一個Cookie。客戶端瀏覽器會把Cookie保存起來。當瀏覽器再請求該網站時,瀏覽器把請求的網址連同該Cookie一同提交給服務器。服務器檢查該Cookie,以此來辨認用戶狀態。服務器還能夠根據須要修改Cookie的內容。緩存

 

1.3 Cookie的不可跨域名性安全

Cookie具備不可跨域名性。根據Cookie規範,瀏覽器訪問Google只會攜帶Google的Cookie,而不會攜帶Baidu的Cookie。Google也只能操做Google的Cookie,而不能操做Baidu的Cookie。Cookie在客戶端是由瀏覽器來管理的。瀏覽器可以保證Google只會操做Google的Cookie而不會操做Baidu的Cookie,從而保證用戶的隱私安全。瀏覽器判斷一個網站是否能操做另外一個網站Cookie的依據是域名。Google與Baidu的域名不同,所以Google不能操做Baidu的Cookie。服務器

 

1.4 Unicode編碼:保存中文cookie

中文與英文字符不一樣,中文屬於Unicode字符,在內存中佔4個字符,而英文屬於ASCII字符,內存中只佔2個字節。Cookie中使用Unicode字符時須要對Unicode字符進行編碼,不然會亂碼。Cookie中保存中文只能編碼。通常使用UTF-8編碼便可。不推薦使用GBK等中文編碼,由於瀏覽器不必定支持,並且JavaScript也不支持GBK編碼。網絡

 

1.5 設置Cookie的全部屬性

 

 

 

 

 

屬  性  名

 

描    述

 

String name

 

該Cookie的名稱。Cookie一旦建立,名稱便不可更改

 

Object value

 

該Cookie的值。若是值爲Unicode字符,須要爲字符編碼。若是值爲二進制數據,則須要使用BASE64編碼

 

Int maxAge

該Cookie失效的時間,單位秒。若是爲正數,則該Cookie在maxAge秒以後失效。若是爲負數,該Cookie爲臨時Cookie,關閉瀏覽器即失效,瀏覽器也不會以任何形式保存該Cookie。若是爲0,表示刪除該Cookie。默認爲–1

 

Boolean secure

該Cookie是否僅被使用安全協議傳輸。安全協議。安全協議有HTTPS,SSL等,在網絡上傳輸數據以前先將數據加密。默認爲false

 

String path

 

該Cookie的使用路徑。若是設置爲「/sessionWeb/」,則只有contextPath爲「/sessionWeb」的程序能夠訪問該Cookie。若是設置爲「/」,則本域名下contextPath均可以訪問該Cookie。注意最後一個字符必須爲「/」

 

String domain

能夠訪問該Cookie的域名。若是設置爲「.google.com」,則全部以「google.com」結尾的域名均可以訪問該Cookie。注意第一個字符必須爲「.」

 

String comment

該Cookie的用處說明。瀏覽器顯示Cookie信息的時候顯示該說明

 

int version

 

該Cookie使用的版本號。0表示遵循Netscape的Cookie規範,1表示遵循W3C的RFC 2109規範

 

1.6 Cookie的修改、刪除

Cookie並不提供修改、刪除操做。若是要修改某個Cookie,只須要新建一個同名的Cookie,添加到response中覆蓋原來的Cookie。若是要刪除某個Cookie,只須要新建一個同名的Cookie,並將maxAge設置爲0,並添加到response中覆蓋原來的Cookie。注意是0而不是負數。負數表明其餘的意義。讀者能夠經過上例的程序進行驗證,設置不一樣的屬性。修改、刪除Cookie時,新建的Cookie除value、maxAge以外的全部屬性,例如name、path、domain等,都要與原Cookie徹底同樣。不然,瀏覽器將視爲兩個不一樣的Cookie不予覆蓋,致使修改、刪除失敗。

 

1.7 Cookie的域名

Cookie是不可跨域名的。域名www.google.com頒發的Cookie不會被提交到域名www.baidu.com去。這是由Cookie的隱私安全機制決定的。隱私安全機制可以禁止網站非法獲取其餘網站的Cookie。正常狀況下,同一個一級域名下的兩個二級域名如www.helloweenvsfei.com和images.helloweenvsfei.com也不能交互使用Cookie,由於兩者的域名並不嚴格相同。若是想全部helloweenvsfei.com名下的二級域名均可以使用該Cookie,須要設置Cookie的domain參數,例如:

Cookie cookie = new Cookie("time","20080808"); // 新建Cookie

cookie.setDomain(".helloweenvsfei.com");           // 設置域名

cookie.setPath("/");                              // 設置路徑

cookie.setMaxAge(Integer.MAX_VALUE);               // 設置有效期

response.addCookie(cookie);                       // 輸出到客戶端

domain參數必須以點(".")開始。另外,name相同但domain不一樣的兩個Cookie是兩個不一樣的Cookie。若是想要兩個域名徹底不一樣的網站共有Cookie,能夠生成兩個Cookie,domain屬性分別爲兩個域名,輸出到客戶端。

 

1.8 Cookie的路徑

domain屬性決定運行訪問Cookie的域名,而path屬性決定容許訪問Cookie的路徑(ContextPath)。例如,若是隻容許/sessionWeb/下的程序使用Cookie,能夠這麼寫:

Cookie cookie = new Cookie("time","20080808");     // 新建Cookie

cookie.setPath("/session/");                          // 設置路徑

response.addCookie(cookie);                           // 輸出到客戶端

設置爲「/」時容許全部路徑使用Cookie。path屬性須要使用符號「/」結尾。name相同但domain相同的兩個Cookie也是兩個不一樣的Cookie。

頁面只能獲取它屬於的Path的Cookie。例如/session/test/a.jsp不能獲取到路徑爲/session/abc/的Cookie。使用時必定要注意。

 

1.9 Cookie的安全屬性

HTTP協議不只是無狀態的,並且是不安全的。使用HTTP協議的數據不通過任何加密就直接在網絡上傳播,有被截獲的可能。使用HTTP協議傳輸很機密的內容是一種隱患。若是不但願Cookie在HTTP等非安全協議中傳輸,能夠設置Cookie的secure屬性爲true。瀏覽器只會在HTTPS和SSL等安全協議中傳輸此類Cookie。下面的代碼設置secure屬性爲true:

Cookie cookie = new Cookie("time", "20080808"); // 新建Cookie

cookie.setSecure(true);                           // 設置安全屬性

response.addCookie(cookie);                        // 輸出到客戶端

secure屬性並不能對Cookie內容加密,於是不能保證絕對的安全性。若是須要高安全性,須要在程序中對Cookie內容加密、解密,以防泄密。

 

1.10 JavaScript操做Cookie

Cookie是保存在瀏覽器端的,所以瀏覽器具備操做Cookie的先決條件。瀏覽器可使用腳本程序如JavaScript或者VBScript等操做Cookie。這裏以JavaScript爲例介紹經常使用的Cookie操做。例以下面的代碼會輸出本頁面全部的Cookie。

<script>document.write(document.cookie);</script>

因爲JavaScript可以任意地讀寫Cookie,有些好事者便想使用JavaScript程序去窺探用戶在其餘網站的Cookie。不過這是徒勞的,W3C組織早就意識到JavaScript對Cookie的讀寫所帶來的安全隱患並加以防備了,W3C標準的瀏覽器會阻止JavaScript讀寫任何不屬於本身網站的Cookie。換句話說,A網站的JavaScript程序讀寫B網站的Cookie不會有任何結果。

 

  1. UserData

由Microsoft公司在IE5.0中引入,指保存在用戶本地終端的一塊持久化字符串數據,除非手動刪除或設置過時時間,不然數據將一直保存,只有IE5.0-IE9.0支持。它藉助DHTML的behaviour屬性來存儲本地數據,容許每一個頁面最多存儲64K數據,每一個站點最多存儲640K數據。它的缺點也是致命的,它並不是Web標準,只有IE5.0-9.0支持,沒法有效解決棘手的瀏覽器兼容問題。

userData的存儲機制:將要保存的數據以「健值對(健做爲屬性,值爲屬性的值)」的形式保存在XML文檔中。userData行爲提供了一個比Cookie更具備動態性和更大容量的數據結構。每頁的UserData存儲區數據大小能夠達到64 Kb,每一個域名能夠達到640 Kb。

userData行爲經過sessions爲每一個對象分配UserData存儲區。使用save和load方法將UserData存儲區數據保存在緩存(cache)中。一旦UserData存儲區保存之後,即便IE瀏覽器關閉或者刷新了,下一次進入該頁面,數據也可以從新載入而不會丟失,除非你人爲刪除或者用腳本設置了該數據的失效期。

2.1 userData使用前必須在行內或者文檔的HEAD部分宣告以下樣式:

<STYLE>
      .userData {behavior:url(#default#userdata);}

 </STYLE>

或者使用腳本綁定:
object.style.behavior = "url('#default#userData')"
object.addBehavior ("#default#userData")

2.2 成員

Expires

設置或取得使用userData行爲保存數據的失效日期。腳本語法:對象ID.expires = 參數參數是一個使用UTC(Universal Time Coordinate,世界調整時間)格式表示失效日期的字符串。該屬性能夠讀寫,沒有默認值。瀏覽器會對比這個日期和當前日期,若是到期,該數據就自動失效。
getAttribute(key)取得指定的屬性值。
load(存儲區名)從UserData存儲區載入存儲的對象數據。
removeAttribute(key)從對象中刪除指定的屬性值。
save(存儲區名) 將對象數據存入一個UserData存儲區。
setAttribute(key, value)設置指定的屬性值。
XMLDocument 取得存儲該對象數據的XML DOM引用。

例:

o.setAttribute("code", "hello world!");
o.save("baidu");

實際上就是一個XML文件,經過文件名->屬性的方式保存字符串。

執行後,UserData文件夾中會生成一個baidu[1].xml文件,其中的內容是:
<ROOTSTUB code="hello,world!"/>

在一個文件中能夠有多個屬性,也就是能夠存儲多種不一樣的數據。

 

 

 

  1. Flash SharedObject

它容許你在本地客戶端的硬盤或是服務器上存儲全部flash支持的數據(Number, String, Array, Boolean, Object, XML等),數據會永久性保存,沒有過時時間,能夠經過設置管理器或調用clear()方法清除。按存放位置能夠分爲本地共享對象和遠程共享對象。默認存儲大小爲100KB,用戶能夠手動設置,最大爲10M。它的問題一樣致命,做爲flash,它擁有flash擁有的安全、穩定性低,耗系統資源等全部缺點。

 

  1. Google Gears

Google於07年發佈的一個開源瀏覽器插件,內置了一個基於SQLite的嵌入式SQL數據庫,並提供了統一的API訪問數據庫。在取得用戶受權以後,每一個站點能夠在數據庫中存儲大小不限的數據。可是Google早在chrome 12.0 中就已經放棄了對它的支持。

 

  1. WebStorage

相對於上述本地存儲方案,以後提出的HTML5本地存儲中的WebStorage本地存儲獲得了最普遍的支持。瀏覽器兼容版本有IE8+/Chrome4+/FireFox3.5+/Safari4+/Opera10.5+。它包括localStorage和sessionStorage兩種存儲方式,均只保存字符串類型。Firefox3.5+/Opera10.5+/IE8+都支持最大存儲5M的數據,而Chrome4+/Safari4+支持最大存儲2.5M的數據。

localStorage用於持久化的本地存儲,瀏覽器窗口關閉後,localStorage存儲的數據仍然能夠被訪問。全部瀏覽器窗口能夠共享localStorage的數據,保存的數據永遠不會過時,只能手動刪除。

而sessionStorage用於本地存儲一個會話中的數據,它不是一種持久化的本地存儲。這些數據只有在同一個會話中的頁面才能訪問,當前頁面不能夠訪問新開頁面的數據,而且會話結束後數據也隨之銷燬而沒法使用。

Name

Description

length

獲取存儲的鍵值對的數量

remainingSpace

獲取存儲空間剩餘空間的大小(非標準,僅IE8.0+支持)

setItem(key, value)

將value值存儲到本地的key字段

removeItem(key)

刪除指定key本地存儲的值

getItem(key)

獲取指定key本地存儲的值

clear()

刪除localStorage中存儲的全部數據

key(index)

根據索引獲取一個指定位置的鍵名

WebStorage容量大、易用、原生支持等優勢都使它成爲首選的本地存儲方案,固然它的安全性也較差,不能用它來保存敏感信息。

 

  1. Indexed Database API

Indexed Database 是Oracle於2009年提出的,簡稱IndexedDB,是一種能讓你在用戶的瀏覽器中持久地存儲結構化數據的數據庫,爲web應用提供了豐富的查詢能力。它使用對象來保存數據,按域名分配獨立空間,一個獨立域名下能夠建立多個數據庫,每一個數據庫能夠建立多個對象存儲空間,一個對象存儲空間至關於一個數據庫表,能夠存儲多個對象數據。目前僅Chrome11+/Firefox4+/IE10支持。Firefox4+支持最大存儲50MB的數據(移動端5MB),chrome11+支持最大存儲5MB的數據。

IndexedDB的基本工做模式是:
1) 打開數據庫並開始一個事務
2) 建立一個對象存儲空間做爲一種交互操做對象(object store)
3) 構建請求來執行數據庫操做,如增長或查詢數據
4) 經過監聽DOM事件來等待操做完成
5) 最後處理「請求」結果(能夠在request對象中找到)

window.indexedDB=window.indexedDB||window.webkitIndexedDB||window.msIndexedDB||window.mozIndexedDB;   //瀏覽器兼容

var request = indexedDB.open("MyTestDB");

request.onsuccess = function(event){

  var db = request.result;

}

request.onerror = function(event){

  console.log("open error and errorCode is"+ request.errorCode );

}

 

上面代碼首先調用IndexedDB對象惟一的方法open()方法打開名爲」MyTestDB」的數據庫,若是不存在,則會被建立。open()方法不會馬上打開數據庫或者開始一個事務,它會返回一個咱們能夠做爲事件來處理的包含result或者錯誤值的IDBOpenDBRequest對象。該對象有success和error事件屬性。若是成功打開,會觸發success事件,咱們能夠在事件處理程序裏保存request.result這個IDBDatabase實例以供後面使用,若是發生錯誤,好比用戶不容許你的web應用訪問以建立一個數據庫,則error事件會在request上觸發。

var appData = [{appId:"9100", appName:"生活", appVersion:1},

{appId:"8920", appName:"娛樂", appVersion:2}];

request.onupgraddeneeded = function(event){

  var db = event.target.result;

  var objectStore = db.createObjectStore("Apps", {keyPath: "appId"});

  objectSotre.createIndex("appName","appName", {unique:false});

  for(var i in appData){

    objectStore.add(appData[i]);

  }

}

上述代碼調用creatObjectStore()方法建立了一個名爲Apps的對象存儲空間,而且定義了一個使得存儲空間中每一個對象都是惟一的屬性做爲key path,這個屬性就是appId。存儲空間中的全部對象都必須擁有appId屬性。此外,createIndex()方法建立了一個索引來經過appName查找app,可能會有重名的,因此不能使用unique索引。最後,調用存儲空間對象的add()方法往裏面添加數據。

接下來就是向咱們以前建立的數據庫中增長數據了。可是,在能夠操做數據庫以前,咱們須要開始一個事務。事務來自於你建立的數據庫對象,並且必須給它指定它須要跨越的對象存儲空間。

var transaction = db.transaction(["Apps"], "readwrite");

transaction.oncomplete = function(event){

  //當數據庫添加數據完成時執行的操做

};

transaction.onerror = function(event){

  //添加數據發生錯誤時的錯誤處理

};

var objectStore = transaction.objectStore("Apps");

for(var i in appData){

  var request = objectStore.add(appData[i]);

}

var request2 = objectStore.delete("9100");

request2.onsuccess = function(event){

  //刪除數據成功後執行的操做

};

上面代碼中的transaction()方法接收三個參數並返回一個事務對象。第一個參數是事務但願跨越的對象存儲空間的列表,包含全部須要跨越的對象存儲空間名,這裏就是咱們以前建立的對象存儲空間Apps。後面兩個參數可選,若是第二個參數未指定,默認表示獲得只讀事務。若是想進行寫操做,用上面的"readwrite"指定。擁有了事務對象後,你就能夠經過transaction.objectStore("Apps")從它那拿到在你建立事務前已經指定過的對象存儲空間Apps,再調用add()方法增長你須要的數據和delete方法從數據庫中刪除數據。

 

  1. FileSystem

只是目前來講只有 Chrome瀏覽器對FileSystem API支持的比較好,因此只能運行在Chrome瀏覽器中。

FileSystem提供了文件夾和文件的建立、移動、刪除等操做,大大方便了數據的本地處理, 並且全部的數據都是在沙盒(sandboxed)中,不一樣的web程序不能互相訪問,這就保證了數據 的完整和安全。

 

7.1申請空間

爲了進行數據的存儲,必需要向瀏覽器進行申請,若是是永久存儲還會向用戶進行詢問,只有 贊成後纔會繼續執行。

window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem; window.resolveLocalFileSystemURL=window.resolveLocalFileSystemURL||window.webkitResolveLocalFileSystemURL; 

獲得系統的權限後就能夠向瀏覽器申請空間

window.requestFileSystem(window.PERSISTENT, //persistent(永久) or temporary(臨時) 
1024*1024, //1M 
onInitFs, //成功後的回調函數 
errorHandler); //錯誤後的回調函數

 

7.2判斷是否申請過空間

window.webkitStorageInfo.queryUsageAndQuota(webkitStorageInfo.PERSISTENT, 
function(used, remaining){ 
if(remaining == ""){ 
console.log("未申請空間。"); 
}else{ 
console.log("已使用空間"+used); 
console.log("所有空間"+remaining); 

}, 
errorHandler);

 

7.3讀取本機存儲的數據

window.resolveLocalFileSystemURL(url,function(fileEntry){ console.log(fileEntry); var dirReader = fileEntry.createReader(); var readEntries = function(){ dirReader.readEntries(function(results){ if(!results.length){ create_file_title("默認文件", ""); console.log("沒有文件!"); }else{ console.log("讀取到" + results.length + "個文件"); for(var i = 0; i < results.length; i++){ console.log(results[i].name); getFileContentByName(fileEntry, results[i].name); } } },errorHandler); }; readEntries(); },errorHandler);

相關文章
相關標籤/搜索