常见的基础概念,ViewState、Cookie和Session的描述似乎都太复杂和书面化,没有达到我想象中的简单(注1)。既然觉得别人说的不简单或者让事情变得更难以理解和应用,那么就该自己进行总结,即是为了自己,也是为了别人(注2)。所以我尝试从我个人的角度进行分析,希望能起到加深自己理解和减少别人误解的作用。
概述
1.HTTP协议是无状态的。Web服务器处理完一次请求后立即断开连接,因此即使同一访客同一浏览器进程,仍然无法被服务器端识别。
2.请求之间需要共享数据。共享数据后,才可以实现辨别身份、保持状态、个性化等。即使匿名用户也有避免重新输入、复合条件检索等作用。
请求之间可以通过3种方式达到共享数据的目的: 1.基于页面:表单元素(ViewState)&URL参数。 2.基于客户端:cookie。3.基于服务器+客户端:session。这三种方式与服务器采用那种技术是无关的。
简单说说这3种方式:ViewState受浏览器进程时间限制,无法完成超出浏览器进程的状态保存。cookie可以不受时间限制但受存储数据大小限制,仅能保存少量数据。session不受时间和大小限制,但受服务器资源限制,因为session无论是存储在内存、还是以文件或数据库方式存储都会对服务器效率造成影响。但只有session才能满足某些网站在状态数据存储的规模和安全性的要求。
1.基于页面
基于页面的方式可以在POST访问时通过表单元素(input hidden)传递数据,可以通过在附加URL参数传递数据。基于页面的方式强大的地方在于即使客户端禁用了cookie或javascript,仍对服务器解析不构成影响。ASP.NET的ViewState只是基于页面传递的一种应用。ASP.NET页面将整个页面视为一个包含了所有服务器控件的Web Form,默认的POST的URL只能是当前页。ViewState原本是可以跨页传递的,但由于ASP.NET页面模型所限,只能起到POST当前页面后维护页面数据的作用。 在开始的ASP.NET事件模型中,你无法POST到其他页面。Response.Redirect()还是Server.Transfer()都不可以,前者先POST回当前页后采用页面重定向,即使你Redirect到自身也还是重定向,后者POST到当前页后再采用其他页进行请求处理,虽然返回了其他页的内容,但浏览器中的URL甚至都不会改变。到了ASP.NET 2.0才对客户端提交表单前通过javascript强制POST到其他页的方式实现了客户端POST。而Web Form的action还是当前页面。可能微软也从未想过在其他页面使用ViewState的需要,所以给该属性设置了protected的保护。可是理论上,基于页面的方式,无论是通过附加表单元素还是URL参数,都可以达到一致的效果。
不讨论ASP.NET这种Web Form模型的弊利,我们如果需要考虑客户端禁用了Cookie和JavaScript的情况(一般无需考虑),采用基于页面的方式仍可以帮我们解决两次请求之间共享数据的目的。 在工作经验里,曾有一个PHP的多子站点的纯信息展示类网站,由于唯一的用户就是维护该网站的编辑,编辑需要在访问网站时,对需要修改的地方直接修改,因此采用了ViewState的方式达到目的,根据是否登录来决定是否加载启用在线编辑的javascript文件,加载后每个区域双击即可弹出编辑框,编辑后即使提交通不过仍可继续修改而不会丢失信息。
2.基于客户端
cookie是客户端技术,服务器采用动态网页技术可以从客户端读取请求附加的cookie和向客户端传递cookie,达到了在请求之间共享数据的目的。cookie的本身有着大小的限制,而即使没有限制,携带过大的cookie对于请求的往返来说也是沉重的负担。cookie是应用广泛的维持状态的方式。由于cookie使用HTTP请求头和响应头进行发送和接受,因此是一种服务器无关的技术。
3.基于服务器+客户端
cookie可以设置过期时间,比基于页面的技术更灵活,但只凭借客户端的cookie进行验证安全性存在隐患,而cookie的存储大小又有限制,因此利用服务器端进行存储扩充和验证,这便是session技术。ASP.NET、PHP等都内置了对session的实现,一些大型的网站和框架也提供了自己的session的实现用于满足各自的需求。大多数我们所见的网站,都使用了session技术。ASP.NET默认的session使用服务器内存存储(通过Page.Session属性使用,通过不同的会话提供程序,也可以用数据库或其他的方式存储),PHP默认的方式以服务器端文本存储(同样也支持内存或数据库等自定义方式)。
如何使用?
其实ViewState、Cookie和Session在不同程度上解决不同请求之间的数据共享问题,这3种方式与服务器端采用的是PHP还是ASP.NET无关,这一点尤为重要。ViewState一般采用在页面表单的源代码中保存数据,其限制可想而知,不过用来完成类似防止表单出错重填的功能还是没问题的。cookie采取在客户端以文本方式存放,虽然数据大小受限制且安全存在隐患,但存储少量用户信息还是足够用的。session可以看做是对cookie的加强(不考虑基于url的session),在服务器端二次验证,增强了安全性,利用服务器端资源,可以存储大量数据。这样看来,完全搞不懂为什么会出现对某个具体的网站有采用那种方式的纠结心态。
1.ViewState用于共享页面状态数据可以考虑,即使服务器端没有直接支持,只要采用的是动态网页技术,可以很容易实现。
2.Cookie一般可以满足用户ID、角色、个性化信息的简单存储。
3.Session对于电子商务类网站或需要通过一系列想到页面完成某个任务的网站来说较为实用,因为单纯使用Cookie这时从存储数据的大小和安全性上来说,都很难胜任。
服务器端无论是采用ASP.NET还是PHP等,一般都会默认支持Session。但内置的Session可能会有各种各样的问题,所以不要拿内置的Session来否定Session这种方式的必要性。
一个销售虚拟游戏物品的网站,虽然同时在线人数不是很多,但由于其单个订单包含的信息量,Cookie方式是根本无法满足的。单位内部的查询网站,采用Cookie存储用户ID和角色,完全够用。
如果一个网站Cookie足可以满足,那么搞不懂为什么要用Session。如果一个网站Session方式才能满足需要,搞不懂怎么抛弃Session方式。曾就职于一个以虚拟物品网上交易作为主要业务的公司,其访客无论是否注册都可以将商品放入购物车中,很多wow的商品包含很多自定义参数可供客户调节,无论注册与否都可以生成预付订单,对于未注册用户,即使关闭浏览器的之内,都可以再次访问时查看加入到订单中的商品,难以想象不使用session方式如何正常工作。如果说在cookie中只存储必要的key,再访问时从服务器中获取,这本身就是session的定义。
没有session实际使用的经历,站在可以使用cookie就可以满足需求的前提下去研究session方式在某个具体技术下的实现的缺点而直接否定session是没有意义的,这如同使用扁平结构静态页的角度来抨击树形结构静态页网站的物理结构一样。
小结
搞清某些技术的局限性,来分析是否满足我们的实际需求,就不会把目光局限于技术本身的比较上。
所以,不要把简单的问题搞复杂。实践重要。本来就是为了在两次请求之间传递状态数据,无论请求页面是否是同一页面,只需要考虑低限度那种方式可满足即可。如果不了解cookie的基础知识,请自行baidu或google;如果看了概述就猜到我要说什么,那你在实际工作中有过应用。
关注我们要解决的问题,让本来简单的问题简单。譬如Web服务器上都是静态文件,URL包含了文件的路径和文件名,甚至连URL参数都无法处理,只能采取客户端javascript的伪过滤方式控制内容的显示。后来的动态网页技术可以在服务器端处理URL参数并根据请求动态生成内容,而后MVC方式出现,URL从直接对应路径和文件名到映射Controller和Action。可是两者的区别只在于看待问题的角度不同,没有任何一种是另一种完全可以替代的,或者说,重点应该是能否恰到好处的解决问题。不要讨论Web Form和ASP.NET MVC哪个好,在PHP早就可以任意匹配逻辑结构和物理结构,动态技术是否支持URL映射只是逻辑结构和物理结构映射的问题(几年前写一个只通过一个入动态页入口,实现多个站点的方式,逻辑结构是分类+文章名,访问时URL也是如此,但物理结构只有一个PHP文件作为入口,所有内容全部存储在mysql数据库中,因为需求要求可以通过数据库备份整个网站,可以直接在几十个网站中执行对内容的批量操作,让我对逻辑结构和物理结构的映射一下子所得甚多),影响不到你对业务模型的抽象,对行为接口的提取和对业务流程的处理。
注1:简单原则;注2:行动原则。
概述
1.HTTP协议是无状态的。Web服务器处理完一次请求后立即断开连接,因此即使同一访客同一浏览器进程,仍然无法被服务器端识别。
2.请求之间需要共享数据。共享数据后,才可以实现辨别身份、保持状态、个性化等。即使匿名用户也有避免重新输入、复合条件检索等作用。
请求之间可以通过3种方式达到共享数据的目的: 1.基于页面:表单元素(ViewState)&URL参数。 2.基于客户端:cookie。3.基于服务器+客户端:session。这三种方式与服务器采用那种技术是无关的。
简单说说这3种方式:ViewState受浏览器进程时间限制,无法完成超出浏览器进程的状态保存。cookie可以不受时间限制但受存储数据大小限制,仅能保存少量数据。session不受时间和大小限制,但受服务器资源限制,因为session无论是存储在内存、还是以文件或数据库方式存储都会对服务器效率造成影响。但只有session才能满足某些网站在状态数据存储的规模和安全性的要求。
1.基于页面
基于页面的方式可以在POST访问时通过表单元素(input hidden)传递数据,可以通过在附加URL参数传递数据。基于页面的方式强大的地方在于即使客户端禁用了cookie或javascript,仍对服务器解析不构成影响。ASP.NET的ViewState只是基于页面传递的一种应用。ASP.NET页面将整个页面视为一个包含了所有服务器控件的Web Form,默认的POST的URL只能是当前页。ViewState原本是可以跨页传递的,但由于ASP.NET页面模型所限,只能起到POST当前页面后维护页面数据的作用。 在开始的ASP.NET事件模型中,你无法POST到其他页面。Response.Redirect()还是Server.Transfer()都不可以,前者先POST回当前页后采用页面重定向,即使你Redirect到自身也还是重定向,后者POST到当前页后再采用其他页进行请求处理,虽然返回了其他页的内容,但浏览器中的URL甚至都不会改变。到了ASP.NET 2.0才对客户端提交表单前通过javascript强制POST到其他页的方式实现了客户端POST。而Web Form的action还是当前页面。可能微软也从未想过在其他页面使用ViewState的需要,所以给该属性设置了protected的保护。可是理论上,基于页面的方式,无论是通过附加表单元素还是URL参数,都可以达到一致的效果。
不讨论ASP.NET这种Web Form模型的弊利,我们如果需要考虑客户端禁用了Cookie和JavaScript的情况(一般无需考虑),采用基于页面的方式仍可以帮我们解决两次请求之间共享数据的目的。 在工作经验里,曾有一个PHP的多子站点的纯信息展示类网站,由于唯一的用户就是维护该网站的编辑,编辑需要在访问网站时,对需要修改的地方直接修改,因此采用了ViewState的方式达到目的,根据是否登录来决定是否加载启用在线编辑的javascript文件,加载后每个区域双击即可弹出编辑框,编辑后即使提交通不过仍可继续修改而不会丢失信息。
2.基于客户端
cookie是客户端技术,服务器采用动态网页技术可以从客户端读取请求附加的cookie和向客户端传递cookie,达到了在请求之间共享数据的目的。cookie的本身有着大小的限制,而即使没有限制,携带过大的cookie对于请求的往返来说也是沉重的负担。cookie是应用广泛的维持状态的方式。由于cookie使用HTTP请求头和响应头进行发送和接受,因此是一种服务器无关的技术。
3.基于服务器+客户端
cookie可以设置过期时间,比基于页面的技术更灵活,但只凭借客户端的cookie进行验证安全性存在隐患,而cookie的存储大小又有限制,因此利用服务器端进行存储扩充和验证,这便是session技术。ASP.NET、PHP等都内置了对session的实现,一些大型的网站和框架也提供了自己的session的实现用于满足各自的需求。大多数我们所见的网站,都使用了session技术。ASP.NET默认的session使用服务器内存存储(通过Page.Session属性使用,通过不同的会话提供程序,也可以用数据库或其他的方式存储),PHP默认的方式以服务器端文本存储(同样也支持内存或数据库等自定义方式)。
如何使用?
其实ViewState、Cookie和Session在不同程度上解决不同请求之间的数据共享问题,这3种方式与服务器端采用的是PHP还是ASP.NET无关,这一点尤为重要。ViewState一般采用在页面表单的源代码中保存数据,其限制可想而知,不过用来完成类似防止表单出错重填的功能还是没问题的。cookie采取在客户端以文本方式存放,虽然数据大小受限制且安全存在隐患,但存储少量用户信息还是足够用的。session可以看做是对cookie的加强(不考虑基于url的session),在服务器端二次验证,增强了安全性,利用服务器端资源,可以存储大量数据。这样看来,完全搞不懂为什么会出现对某个具体的网站有采用那种方式的纠结心态。
1.ViewState用于共享页面状态数据可以考虑,即使服务器端没有直接支持,只要采用的是动态网页技术,可以很容易实现。
2.Cookie一般可以满足用户ID、角色、个性化信息的简单存储。
3.Session对于电子商务类网站或需要通过一系列想到页面完成某个任务的网站来说较为实用,因为单纯使用Cookie这时从存储数据的大小和安全性上来说,都很难胜任。
服务器端无论是采用ASP.NET还是PHP等,一般都会默认支持Session。但内置的Session可能会有各种各样的问题,所以不要拿内置的Session来否定Session这种方式的必要性。
一个销售虚拟游戏物品的网站,虽然同时在线人数不是很多,但由于其单个订单包含的信息量,Cookie方式是根本无法满足的。单位内部的查询网站,采用Cookie存储用户ID和角色,完全够用。
如果一个网站Cookie足可以满足,那么搞不懂为什么要用Session。如果一个网站Session方式才能满足需要,搞不懂怎么抛弃Session方式。曾就职于一个以虚拟物品网上交易作为主要业务的公司,其访客无论是否注册都可以将商品放入购物车中,很多wow的商品包含很多自定义参数可供客户调节,无论注册与否都可以生成预付订单,对于未注册用户,即使关闭浏览器的之内,都可以再次访问时查看加入到订单中的商品,难以想象不使用session方式如何正常工作。如果说在cookie中只存储必要的key,再访问时从服务器中获取,这本身就是session的定义。
没有session实际使用的经历,站在可以使用cookie就可以满足需求的前提下去研究session方式在某个具体技术下的实现的缺点而直接否定session是没有意义的,这如同使用扁平结构静态页的角度来抨击树形结构静态页网站的物理结构一样。
小结
搞清某些技术的局限性,来分析是否满足我们的实际需求,就不会把目光局限于技术本身的比较上。
所以,不要把简单的问题搞复杂。实践重要。本来就是为了在两次请求之间传递状态数据,无论请求页面是否是同一页面,只需要考虑低限度那种方式可满足即可。如果不了解cookie的基础知识,请自行baidu或google;如果看了概述就猜到我要说什么,那你在实际工作中有过应用。
关注我们要解决的问题,让本来简单的问题简单。譬如Web服务器上都是静态文件,URL包含了文件的路径和文件名,甚至连URL参数都无法处理,只能采取客户端javascript的伪过滤方式控制内容的显示。后来的动态网页技术可以在服务器端处理URL参数并根据请求动态生成内容,而后MVC方式出现,URL从直接对应路径和文件名到映射Controller和Action。可是两者的区别只在于看待问题的角度不同,没有任何一种是另一种完全可以替代的,或者说,重点应该是能否恰到好处的解决问题。不要讨论Web Form和ASP.NET MVC哪个好,在PHP早就可以任意匹配逻辑结构和物理结构,动态技术是否支持URL映射只是逻辑结构和物理结构映射的问题(几年前写一个只通过一个入动态页入口,实现多个站点的方式,逻辑结构是分类+文章名,访问时URL也是如此,但物理结构只有一个PHP文件作为入口,所有内容全部存储在mysql数据库中,因为需求要求可以通过数据库备份整个网站,可以直接在几十个网站中执行对内容的批量操作,让我对逻辑结构和物理结构的映射一下子所得甚多),影响不到你对业务模型的抽象,对行为接口的提取和对业务流程的处理。
注1:简单原则;注2:行动原则。