网页的安全和隐私
自从有了动态网页以来,在网页中进行注册登录已经成为了动态网页的标配。与此同时,人们也在不断改善和优化网页,以带给用户更好的浏览效果。很自然的,人们在登录页面也做了很多优化,比如客户端校验,客户端导航提示。由于浏览器无法对用户的操作做任何限制,人们可以随时打开,随手关闭,当人们多次访问同一个网页时,难免会出现反复登录的情况,这时候人们希望有一种记忆功能,能够记忆之前输入过的账户或密码,避免人们反复输入。早先的做法是将账户密码写入硬盘,可以反复读取,但是硬盘是一个公共区域,任何程序都可以读取,这极不安全。虽然用户愿意将个人信息在网页上进行填写,但不表示他们愿意将这些信息永久地保存在硬盘,但有人就这么做了,最终导致了一些用户直接禁用本地存储功能。本文讨论一些更为安全的本地存储以提升用户体验,尽管如此,对于这些本地存储也不能滥用,一旦滥用,同样有遭到禁用的风险。
Web存储
这是一个新概念,随HTML5标准提出来的,后来又从HTML5中分离出来成为一个独立的标准。目前客户端的实现主要包含在localStorage和sessionStorage对象中。目前所有主流浏览器都支持该实现,早期浏览器不支持。localStorage和sessionStorage是持久化关联数组,是名值对映射表,支持大容量数据存储。和使用普通的JavaScript对象没有什么区别。localStorage和sessionStorage的区别是存储的有效期和作用域不同。关于它们的使用,请参考下面的代码片段:
var name = localStorage.username;
name = localStorage["username"];
if(!name){
name = prompt("What is your name?");
localStorage.username = name;
}
for(var name in localStorage)
{
var value = localStorage[name];
}
标准规定,Web存储不仅可以存储原始类型的数据,也可以存储对象和数组,还可以存储日期,正则,甚至文件对象等内置类型的数据。
Web存储的有效期和作用域
localStorage的有效期是永久,除非是程序对数据进行了删除,否则数据永不过期。localStorage的作用域受同源策略影响,同源的网页之间可以共享localStorage,可以相互读取对方的数据,也可以修改和覆盖对方的数据,非同源网页之间则不行。同源策略指的是协议,域名,端口号相同的网页之间可以相互访问对方的数据。另外一点需要注意,localStorage也受浏览器的影响,比如说,firefox的存储的数据可能在Ie上就访问不到。sessionStorage的有效期是当前页面,一旦页面关闭,数据也被清除。sessionStorage的作用域同样受同源策略影响,只有同源网页才能共享数据,并且网页还必须在一个窗口中,也就是说,只有处于一个窗口中的两个iframe才能共享数据。不同窗口的同源网页也不能共享数据。
Web存储API
localStorage和sessionStorage的使用方式非常相似。以localStorage为例,下面的的代码对sessionStorage同样适用。
localStorage.setItem("x", 1);//存储一个数值
localStorage.getItem("x");//获取数值
//枚举所有名/值对
for(var i = 0; i < localStorage.length; i++)
{
var name = localStorage.key(i);
var value = localStorage.getItem(name);
}
localStorage.removeItem("x");//删除一项
localStorage.clear();//删除所有
上述代码中有一个值得探讨的地方是,localStorage的存储我们为何不写成localStorage.x = 1?这样似乎更简洁明了。取值的时候直接localStorage.x,这样书写岂不是更简单?的确是更简单。但是标准规定存储对象只能存储数据的副本,程序对数据的改变不能影响存储对象。以下面的代码为例:
localStorage.o = {x:1};
localStorage.o.x = 2;
localStorage.o.x;
如果我们在程序中使用这样的代码,那么我们每次修改数据都直接影响了存储数据,这显然是和标准冲突,也不符合我们日常的需求,用户通常都是在所有信息填写完成后,一次性存储所有数据,而不是每填写一项就保存一次。我们对代码稍做修改,如下面这样,就符合标准,也更符合日常实际。
var obj = localStorage.getItem("o");
obj.x = 2;
obj.y = 3;
localStorage.setItem("o", obj);
Web存储事件
一旦页面的localStorage或者sessionStorage发生改变,那么当前的同源页面就会收到存储事件。需要注意的是数据发生改变的页面不会收到事件。可以通过addEventListener()方法注册事件处理程序,代码如下:
window.addEventListener("storage", function(event){
/*
event的几个重要属性:
1.key
项目名字
2.newValue
新值
3.oldVlue
旧值
4.storageArea
存储对象
5.url
触发存储事件的文档URL
*/
})
需要注意的是,由于存储事件采用的是广播机制,因此localStorage会广播所有访问同一站点的窗口,比如我们在首页设置停止动画,那么所有其他详情页都会收到广播事件,从而都停止动画,sessionStorage则不会这样。
Cookie
Cookie是一种比较古老的技术。它最初的目的是为了让服务器识别客户端身份,以便给不同身份的客户端提供个性化服务,这就是我们说的动态网页技术。Cookie是动态网页的基石,由于Http协议是无状态的,每次请求完成后就关闭连接,因此状态保持无法通过Http协议自身来完成,Cookie解决了这个问题。Cookie的使用非常简单,和上面的Web存储类似,这里不多做介绍。需要注意的是Cookie的有效期可以通过max-age进行设置。另外Cookie也严格遵守同源策略,作用域可以通过path和domain进行设置,Cookie只对当前页和当前页的子路径下的页面是可见的。
Cookie的局限性
Cookie的特殊之处在于每次请求都会带上Cookie信息,就好比你每次去政府机关办事都必须带上身份证一样,因此Cookie不太适合存储大量的信息。RFC2965标准不允许浏览器保存超过300个Cookie,同时为每个Web服务器保存的Cookie不能超过20个,而且每个Cookie保存的数据不能超过4K。理论上来说,Cookie的数量和大小都不应该做任何限制,但是出于性能的考虑,我们在实际应用中就不得不做上述限制。
其他客户端存储
IE userData
在IE5以上的版本中,可以给Html元素附加一个userData行为,从而使该元素具有load和save方法,用于载入和保存客户端存储的数据。它的作用域比Cookie小,只在当前目录有效,不包含子目录,存储的数据量比Cookie大。具体的,可查阅更详细的相关文档。因为该功能只在IE上有效,因此适用范围很有限。
应用程序存储
和localStorage不同的,应用程序存储不是仅仅保存数据,而是将整个页面保存下来。同时应用程序缓存不会因为清除浏览器缓存而清除掉,它更像是一个安装在浏览器端的一个固定的应用。除非是用户手动删除,否则它就永久的驻扎在那里。应用程序缓存包含一系列页面,是一个完整的网页应用。因此,它有一个缓存清单。有关应用程序缓存,需要较大篇幅叙述,具体的,可以参考更专业的文档。应用程序存储是HTML5标准新增的功能,各主流浏览器都支持。
好了,关于客户端存储就是这些,你都掌握了吗?