浏览器的本地存储出来也有段时间了。Firefox 是从 2开始支持的,IE 似乎是从 8 才开始支持。 Google Chome 似乎暂时还不支持。
关于客户端存储的标准,可以参考这里:
http://www.whatwg.org/specs/web-apps/current-work/#scs-client-side
这一个存储是基于DOM的,也可以说是未来各个浏览器都会支持的一项功能。
浏览器客户端存储方式主要有四种:
1、 cookie
2、 flash shared object
3、 IE的 userdata
4、 DOM storage
我在 anehta 的水印系统中,使用的是第二种方式:FSO。
yahoo 在 安全印章系统中,还同时使用了 第三种,IE 的 userdata。 不过这个存储的地方在高版本的IE中好像支持不好。 所以未来的趋势肯定是利用 DOM storage。
DOM storage 分为两种, 一个是 叫做 sessionStorage,另一个叫做 localStorage,这是IE的叫法,在 Firefox 中叫做 globalStorage。(sessionStorage是FF,IE通用)
从名字就可以看出,sessionStorage是和当前窗口相关的,而localStorage 则是和当前窗口无关的,关了浏览器再开起来还会存在,还能读到。
对于 javascript 来说, dom storage 实际上就是一个数组。通过非常简单的API调用方式就能够使用DOM Storage。
设置一个值: window.sessionStorage.setItem(key, value);
读取一个值: window.sessionStorage.getItem(key);
还有其他API,可以参考相关手册。
而 IE 的 localStorage 和 FF的 globalStorage 还是有差别的.
globalStorage 有区分域。
window.globalStorage.namedItem(domain).setItem(key, value);
通过 namedItem 可以设置域,跨域的访问在FF出会抛出一个安全错误的异常。
FF 的 globalStorage 是使用
SQLite 的方式来存储的。每个域下都有5M的空间,远远大于cookie能存储的值。
前段时间,gmail 的iphone版好像开始存储数据到 localStorage 中,我的博客中也曾经 记载这个事情。有安全专家曾担心可能会出现一些对该storage的注射,还需要深度挖掘下利用方式。
我们知道,XSS Payload 实际上也可以看成是一个javascript的应用,所以使用 DOM Storage ,在XSS中也会起到一些更好的用户体验。
其中最主要的一个作用就是
跨页面传递数据。
无论是sessionStorage 还是 localStorage,都能够起到这个作用。
对于这一点,luoluo在 webzine0x03 中有一篇文章提到了一些tips。那么,现在又多了一种方法了!不同于window对象的是,localStorage是不依赖于当前窗口的!
不同于cookie,
localStorage 是用户清理了cookie之后还存在的,一般是没有 expire 时间的,应该会比较好用。
为了方便有兴趣的朋友继续研究,整理一些参考资料如下:
http://www.niallkennedy.com/blog/2007/01/ajax-performance-local-storage.html
http://ajaxian.com/archives/firefox-2-client-side-storage-and-a-lot-more
https://developer.mozilla.org/en/Storage
http://ejohn.org/blog/dom-storage/
http://www.xul.fr/en/html5/sessionstorage.php
I was a tad disappointed when I found out that localStorage
only supports storing strings, since I was hoping for something more structured. But withnative JSON support it’s easy to create an object store on top of localStorage
:
Storage.prototype.setObject = function(key, value) {
this.setItem(key, JSON.stringify(value));
}
Storage.prototype.getObject = function(key) {
return JSON.parse(this.getItem(key));
}
localStorage
databases are scoped to an HTML5 origin, basically the tuple(scheme, host, port)
. This means that the database is shared across all pages on the same domain, even concurrently by multiple browser tabs. However, a page connecting over http://
cannot see a database that was created during an https://
session.
localStorage
and sessionStorage
are supported by Firefox 3.5, Safari 4.0, and IE8. You can find more compatibility details on quirksmode.org, including more detail on the storage event.
//下面将UserData
应用范围
UserData是微软为IE专门在系统中开辟的一块存储空间,所以说只支持Windows+IE的组合,实际测试在2000(IE5.5)、XP(IE6、IE7),Vista(IE7)下都是可以正常使用的。
在哪儿?
在XP下,一般位于C:\Documents and Settings\用户名\UserData,有些时候会在C:\Documents and Settings\用户名\Application Data\Microsoft\Internet Explorer\UserData。
在Vista下,位于C:\Users\用户名\AppData\Roaming\Microsoft\Internet Explorer\UserData。
容量
网页制作完成手册中这样说:
Security Zone |
Document Limit (KB) |
Domain Limit (KB) |
Local Machine |
128 |
1024 |
Intranet |
512 |
10240 |
Trusted Sites |
128 |
1024 |
Internet |
128 |
1024 |
Restricted |
64 |
640 |
线上使用时,单个文件的大小限制是128KB,一个域名下总共可以保存1024KB的文件,文件个数应该没有限制。在受限站点里这两个值分别是64KB和640KB,所以如果考虑到各种情况的话,单个文件最好能控制64KB以下。
如何使用?
用下面的JS语句就可以建立一个支持UserData的对象:
o = document.createElement('input');
o.type = "hidden";
o.addBehavior ("#default#userData");
//UserData.o.style.behavior = "url('#default#userData')" ;
//上面的语句也是一样的作用
document.body.appendChild(o);
说白了UserData就是样式里的一个Behavior,所以这样写也是一样的:
<input type=hidden class= storeuserData />
<style>
.storeuserData {behavior:url(#default#userData);}
</style>
UserData可以绑定在大多数的html标签上,具体为:
A, ACRONYM, ADDRESS, AREA, B, BIG, BLOCKQUOTE, BUTTON, CAPTION, CENTER, CITE, CODE, DD, DEL, DFN, DIR, DIV, DL, DT, EM, FONT, FORM, hn, HR, I, IMG, INPUT type=button, INPUT type=checkbox, INPUT type=file, INPUT type=hidden, INPUT type=image, INPUT type=password, INPUT type=radio, INPUT type=reset, INPUT type=submit, INPUT type=text, KBD, LABEL, LI, LISTING, MAP, MARQUEE, MENU, OBJECT, OL, OPTION, P, PLAINTEXT, PRE, Q, S, SAMP, SELECT, SMALL, SPAN, STRIKE, STRONG, SUB, SUP, TABLE, TEXTAREA, TT, U, UL, VAR, XM
UserData对象有以下的属性和方法:
属性 |
描述 |
expires |
设置或读取文件过期时间 |
XMLDocument |
读取文件的XML DOM |
方法 |
描述 |
getAttribute |
读取指定属性的值 |
load |
打开文件 |
removeAttribute |
删除指定的属性 |
save |
保存文件 |
setAttribute |
为指定属性赋值 |
UserData文件实际上就是一个XML文件,通过文件名->属性的方式保存字符串,如以下一段代码:
o.setAttribute("code", "hello world!");
o.save("baidu");
执行后,UserData文件夹中会生成一个baidu[1].xml文件,其中的内容是:
<ROOTSTUB code="hello,world!"/>
在一个文件中可以有多个属性,也就是可以存储多种不同的数据。
在音乐盒链接保存项目里,封装了一个UserData类,这样可以更方便地使用UserData,代码如下:
/** @class 定义userdata的操作 */
var UserData = {
// 定义userdata对象
o : null,
// 设置文件过期时间
defExps : 365,
// 初始化userdate对象
init : function(){
if(!UserData.o){
try{
UserData.o = document.createElement('input');
UserData.o.type = "hidden";
//UserData.o.style.behavior = "url('#default#userData')" ;
UserData.o.addBehavior ("#default#userData");
document.body.appendChild(UserData.o);
}catch(e){
return false;
}
};
return true;
},
// 保存文件到userdata文件夹中 f-文件名,c-文件内容,e-过期时间
save : function(f, c, e){
if(UserData.init()){
var o = UserData.o;
// 保持对象的一致
o.load(f);
// 将传入的内容当作属性存储
if(c) o.setAttribute("code", c);
// 设置文件过期时间
var d = new Date(), e = (arguments.length == 3) ? e : UserData.defExps;
d.setDate(d.getDate()+e);
o.expires = d.toUTCString();
// 存储为制定的文件名
o.save(f);
}
},
// 从uerdata文件夹中读取指定文件,并以字符串形式返回。f-文件名
load : function(f){
if(UserData.init()){
var o = UserData.o;
// 读取文件
o.load(f);
// 返回文件内容
return o.getAttribute("code");
}
},
// 检查userdata文件是否存在 f-文件名
exist : function(f){
return UserData.load(f) != null;
},
// 删除userdata文件夹中的指定文件 f-文件名
remove : function(f){
UserData.save(f, false, -UserData.defExps);
}
// UserData函数定义结束
};
参考资料:
自:http://hi.baidu.com/aullik5/blog/item/60d2b5fc52675a1e09244d77.html
自:http://www.cnblogs.com/QLeelulu/archive/2008/03/29/1129322.html