客戶端存儲方式web
由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不會有任何結果。
由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!"/>
在一個文件中能夠有多個屬性,也就是能夠存儲多種不一樣的數據。
它容許你在本地客戶端的硬盤或是服務器上存儲全部flash支持的數據(Number, String, Array, Boolean, Object, XML等),數據會永久性保存,沒有過時時間,能夠經過設置管理器或調用clear()方法清除。按存放位置能夠分爲本地共享對象和遠程共享對象。默認存儲大小爲100KB,用戶能夠手動設置,最大爲10M。它的問題一樣致命,做爲flash,它擁有flash擁有的安全、穩定性低,耗系統資源等全部缺點。
Google於07年發佈的一個開源瀏覽器插件,內置了一個基於SQLite的嵌入式SQL數據庫,並提供了統一的API訪問數據庫。在取得用戶受權以後,每一個站點能夠在數據庫中存儲大小不限的數據。可是Google早在chrome 12.0 中就已經放棄了對它的支持。
相對於上述本地存儲方案,以後提出的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容量大、易用、原生支持等優勢都使它成爲首選的本地存儲方案,固然它的安全性也較差,不能用它來保存敏感信息。
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方法從數據庫中刪除數據。
只是目前來講只有 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);