Session&Cookie&localStorage
领导让我开发一个有两张信息表单需要提交页面的网站,我作为一名开发人员,这个需求太简单了,和领导说直接存session
session不是http的概念,而是服务器开发框架的概念,这些框架可以针对指定的用户开辟一块内存用来标识那个指定用户,也可以认为是对于我们公司给你的passport,一般session的过期时间是20分钟(以tomcat为例)超过这段时间用户必须重新请求并在服务器中重新生成一个新的passport.我想这样设计,用户填写完第一张表单可以存在服务器的session中,可以是redis也可以是服务器内存中,用户提交第二张表单时提交后,服务器判断这是第二张表单再和session中第一张表单一起交给服务器做后续操作,这样其他人就不可能读到刚刚那个用户提交的数据了,领导对我说,其实使用session有两个巨大安全问题让我再斟酌一下
Cookie这时我又想到了用cookie来实现,cookie是保存客户端的cookie键值对,请求携带cookie发送给服务器进行处理,cookie的过期时间是客户端决定的,默认cookie失效是直到浏览器关闭
回到需求上来,当请求进来时,服务器判断请求头的set-cookie为空,那样就认为这个是第一次用户请求,服务器就返给他一段sessionid,其实这个sessionid关联cookie,当这个用户再次请求页面后,他的浏览器就携带着服务器发给他的那段sessionid,在服务器端对这个sessionid做匹配,发现是我发给你的sessionid,这样这两张表单就可以分两次发送给服务器了,不同的人就会识别不同的sessionid了,领导又和我说还是有安全问题,他提出如果黑客修改了cookie,黑客就可以模拟其他用户id来传第二张表单的数据,其可以进行篡改和伪造,session和cookie是相辅相成的,所以这是session的第一个安全问题(可能有人会说二次加密可以解决问题,我认为加密是可行的,这样数据就不会被篡改)其二,如果我是黑客,写一个脚本循环带有空cookie的内容来请求,那服务器不得不开辟大段内存,造成服务器内存泄露的性能问题,或者随着业务增长访问量导致服务器内存中都是第一张表单的数据,最后服务器内存不足宕机了.当然session还是一个致命的问题,引入有状态和无状态
什么是无状态和有状态?
无状态:就是没有特殊状态的服务,各个请求对于服务器来说统一无差别处理,请求自身携带了所有服务端所需要的所有参数(服务端自身不存储跟请求相关的任何数据,不包括数据库存储信息)
有状态:与其相反,有状态服务在服务端保留之前请求的信息,用以处理当前请求,比如session等
所以状态体现在我们请求的服务器的架构中,有状态情况下请求只能发给一台服务器,而无状态可以横向扩展,所以架构师们想要实现可扩展性必须舍弃框架中的session,或者实现一个的共享存储中,但要面对复杂业务的风险
url重写
通过 Cookie 的方式存储 Session 状态,只是其中一种方式。如果客户端禁用了 Cookie 的话,很多网站任然可以存储用户的信息。一种处理的方式是URL 重写,将 SesseionID 直接附加在请求地址的后面。另一种处理的方式是,使用隐藏自动的方式。就是服务器自动的在表单中,添加一个隐藏字段,以便在表单提交时,将 SesseionID 一起传到服务器,进行识别(通常是将重要信息头啊cookie啊什么的扔到请求头后面写url重写必须要有能解析url重写的机制)
隐藏表单域
(参数存放)参数是存放在请求html实体里的<input type="hidden">,因此没有长度限制,但是不支持 GET 请求方法,因为 GET 没有请求实体
以上cookie,session,url重写,隐藏表单域是目前4大会话跟踪技术
回到正题,当服务器挂了,运维人员对服务器进行重启,因为session是存在内存中而不是存在数据库中,导致所有的session都没了,此时有些用户开始发送第二张表单,因没有提交sessionid服务器就认为用户就是在提交第一张表单,从而导致提交失败,当然负载均衡的出现对这种机制也不是很友好,服务器a,服务器b,不知道提交到那个服务器数据了,有人说数据存数据库不就好了,我们知道从数据库到内存需要时间,这样反复的与数据库交互对服务器性能不是很好.
之后我向领导提出在提交第一张表单之后将表单数据提交到cookie中,等第二张表单提交时,再附加上第一张表单cookie的信息,这样就能避免中断也能提交数据,我认为这是一个完美的方案但是领导说还是有一个缺陷,第一次提交表单没有任何意义,提交只是额外渲染了第二张表单的视图,所以第一次请求就是一次对服务器的流量消耗.
这里就引入localStorage概念
localStorge其实就是本地的存储,其是html5引入的新概念,普通的一条cookie信息存储空间在浏览器只能是4k的大小,而localStorge一般是5M,其通过键值对来存储的,其本身是js下window方法下的一个对象,要注意的是遵循同源策略,即在不同浏览器或者网站或者ip或者协议或者端口是不能使用的
localStorage调用方法及属性
localSorage.key(1)返回当前对象index序号所设置的值,没有返回null
localSorage.setItem(key,value)设置值
localSorage.getItem(key)获取值
localSorage.remoteItem(key)移除
localSorage.clear全部清除
localSorage.length获取长度
localStorage的局限性
1.只支持高版本浏览器,而且各个浏览器大小不统一,IE需要IE8才支持这个属性
2.目前浏览器对localSorage的限定都为string类型,需要变量json要自行改变
var userEntity = { name: 'tom', age: 22 }; // 存储值:将对象转换为Json字符串 localSorage.setItem('user', JSON.stringify(userEntity)); // 取值时:把获取到的Json字符串转换回对象 var userJsonStr = localSorage.getItem('user'); userEntity = JSON.parse(userJsonStr); console.log(userEntity.name); // => tom
3.本质是对字符串的读取, 存储容量过多会使得页面卡顿
4.不能被爬虫抓到
localStorage与sessionStorage区别
localStorage是本地永久存储,除非手动清理
sessionStorage其本身原理,方法和属性与localStorage一致,其是会话关闭后自动清除,会话指的是浏览器窗口(若使用Chrome的恢复标签页功能,seesionStorage的数据也会恢复)
将了那么多localStorage,其实并不安全,黑客可以注入js代码,获取其他用户的localStorge数据,发送到黑客本机,所以能不用就不用.
最后我回到需求的本质,领导让我开发两张信息表单页面提交,我直接用纯js渲染页面不就行了吗,第一张表单用户按下'下一步'按钮,隐藏第一张表单的内容,显示第二张表单数据内容,点击第二张表单的'提交'按钮,这样所有表单的数据就一次性提交成功了,两张页面只需要做一张就行了,也不会有安全隐患,只是对用户来说如果强刷了页面又要从第一张表单开始填起,领导看到我激动的样子,满头黑线,就这个需求就搞了半天,看来我升职加薪是无望了