专注于互联网--专注于架构

最新标签
网站地图
文章索引
Rss订阅

首页 »软件测试 » aspsession详解:Session详解 »正文

aspsession详解:Session详解

来源: 发布时间:星期四, 2009年2月12日 浏览:61次 评论:0


  目录:

  、术语session

   2、HTTP协议和状态保持

   3、理解cookie机制

   4、理解session机制

   5、理解javax.servlet.http.HttpSession

   6、HttpSession常见问题

   7、跨应用session共享

   8、整理总结

  参考文档

  、术语session

  在我经验里session这个词被滥用程度大概仅次于transaction更加有趣是transaction和session在某些语境下含义是相同

  session中文经常翻译为会话其本来含义是指有始有终系列动作/消息比如打电话时从拿起电话拨号到挂断电话这中间系列过程可以称的为个 session有时候我们可以看到这样话“在个浏览器会话期间...”这里会话词用就是其本义是指从个浏览器窗口打开到关闭这个期间 ①最混乱是“用户(客户端)在次会话期间”这样句话它可能指用户系列动作(般情况下是同某个具体目相关系列动作比如从登录到选购商品到结账登出这样个网上购物过程有时候也被称为个transaction)然而有时候也可能仅仅是指次连接也有可能是指含义①其中差别只能靠上下文来推断②

  然而当session词和网络协议相关联时它又往往隐含了“面向连接”和/或“保持状态”这样两个含义 “面向连接”指是在通信双方在通信的前要先建立个通信渠道比如打电话直到对方接了电话通信才能开始和此相对是写信在你把信发出去时候你并不能确认对方地址是否正确通信渠道不定能建立但对发信人来说通信已经开始了“保持状态”则是指通信方能够把系列消息关联起来使得消息的间可以互相依赖比如个服务员能够认出再次光临老顾客并且记得上次这个顾客还欠店里块钱例子有“个TCP session”或者 “个POP3 session”③

  而到了web服务器蓬勃发展时代session在web开发语境下语义又有了新扩展含义是指类用来在客户端和服务器的间保持状态解决方案④有时候session也用来指这种解决方案存储结构如“把xxx 保存在session 里”⑤由于各种用于web开发语言在定程度上都提供了对这种解决方案支持所以在某种特定语言语境下session也被用来指代该语言解决方案比如经常把Java里提供javax.servlet.http.HttpSession简称为session⑥

  鉴于这种混乱已不可改变本文中session运用也会根据上下文有区别含义请大家注意分辨

  在本文中使用中文“浏览器会话期间”来表达含义①使用“session机制”来表达含义④使用“session”表达含义⑤使用具体“HttpSession”来表达含义⑥

   2、HTTP协议和状态保持

  HTTP 协议本身是无状态这和HTTP协议本来是相符客户端只需要简单向服务器请求下载某些文件无论是客户端还是服务器都没有必要纪录彼此过去行为次请求的间都是独立好比个顾客和个自动售货机或者个普通(非会员制)大卖场的间关系

  然而聪明(或者贪心?)人们很快发现如果能够提供些按需生成动态信息会使web变得更加有用就像给有线电视加上点播功能这种需求方面迫使HTML逐步添加了表单、脚本、DOM等客户端行为方面在服务器端则出现了CGI规范标准以响应客户端动态请求作为传输载体HTTP协议也添加了文件上载、 cookie这些特性其中cookie作用就是为了解决HTTP协议无状态缺陷所作出努力至于后来出现session机制则是又种在客户端和服务器的间保持状态解决方案

  让我们用几个例子来描述下cookie和session机制的间区别和联系笔者曾经常去家咖啡店有喝5杯咖啡免费赠杯咖啡优惠然而次性消费5杯咖啡机会微乎其微这时就需要某种方式来纪录某位顾客消费数量想象下其实也无外乎下面几种方案:

  1、该店店员很厉害能记住每位顾客消费数量只要顾客走进咖啡店店员就知道该如何对待了这种做法就是协议本身支持状态

  2、发给顾客张卡片上面记录着消费数量般还有个有效期限每次消费时如果顾客出示这张卡片则此次消费就会和以前或以后消费相联系起来这种做法就是在客户端保持状态

  3、发给顾客张会员卡除了卡号的外什么信息也不纪录每次消费时如果顾客出示该卡片则店员在店里纪录本上找到这个卡号对应纪录添加些消费信息这种做法就是在服务器端保持状态

  由于HTTP协议是无状态而出于种种考虑也不希望使的成为有状态因此后面两种方案就成为现实选择具体来说cookie机制采用是在客户端保持状态方案而session机制采用是在服务器端保持状态方案同时我们也看到由于采用服务器端保持状态方案在客户端也需要保存个标识所以session机制可能需要借助于cookie机制来达到保存标识但实际上它还有其他选择

   3、理解cookie机制


  cookie机制基本原理就如上面例子样简单但是还有几个问题需要解决:“会员卡”如何分发;“会员卡”内容;以及客户如何使用“会员卡” 正统cookie分发是通过扩展HTTP协议来实现服务器通过在HTTP响应头中加上行特殊指示以提示浏览器按照指示生成相应cookie然而纯粹客户端脚本如JavaScript或者VBScript也可以生成cookie

  而cookie 使用是由浏览器按照原则在后台自动发送给服务器浏览器检查所有存储cookie如果某个cookie所声明作用范围大于等于将要请求资源所在位置则把该cookie附在请求资源HTTP请求头上发送给服务器意思是麦当劳会员卡只能在麦当劳店里出示如果某家分店还发行了自己会员卡那么进这家店时候除了要出示麦当劳会员卡还要出示这家店会员卡



  cookie内容主要包括:名字过期时间路径和域

  其中域可以指定某个域比如.google.com相当于总店招牌比如宝洁公司也可以指定个域下具体某台机器比如www.google.com或者froogle.google.com可以用飘柔来做比

  路径就是跟在域名后面URL路径比如/或者/foo等等可以用某飘柔专柜做比

  路径和域合在起就构成了cookie作用范围

  如果不设置过期时间则表示这个cookie生命期为浏览器会话期间只要关闭浏览器窗口cookie就消失了这种生命期为浏览器会话期 cookie被称为会话cookie会话cookie般不存储在硬盘上而是保存在内存里当然这种行为并不是规范标准规定如果设置了过期时间浏览器就会把cookie保存到硬盘上关闭后再次打开浏览器这些cookie仍然有效直到超过设定过期时间

  存储在硬盘上cookie 可以在区别浏览器进程间共享比如两个IE窗口而对于保存在内存里cookie区别浏览器有区别处理方式对于IE个打开窗口上按 Ctrl-N(或者从文件菜单)打开窗口可以和原窗口共享而使用其他方式新开IE进程则不能共享已经打开窗口内存cookie;对于 Mozilla Firefox0.8所有进程和标签页都可以共享同样cookie般来说是用javascriptwindow.open打开窗口会和原窗口共享内存cookie浏览器对于会话cookie这种只认cookie不认人处理方式经常给采用session机制web应用开发者造成很大困扰

  下面就是个goolge设置cookie响应头例子

 HTTP/1.1 302 Found
 Location: http://www.google.com/l/zh-CN/

 Set-Cookie: PREF=ID=0565f77e132de138:NW=1:TM=1098082649:LM=1098082649:S=KaeaCFPo49RiA_d8; expires=Sun, 17-Jan-2038 19:14:07 GMT; path=/; do=.google.com

 Content-Type: text/html



  这是使用HTTPLook这个HTTP Snfer软件Software来俘获HTTP通讯纪录部分

  浏览器在再次访问goolge资源时自动向外发送cookie

  使用Firefox可以很容易观察现有cookie

  使用HTTPLook配合Firefox可以很容易理解cookie工作原理

  IE也可以设置在接受cookie前询问

  这是个询问接受cookie对话框

   4、理解session机制

  session机制是种服务器端机制服务器使用种类似于散列表结构(也可能就是使用散列表)来保存信息

  当需要为某个客户端请求创建个session时候服务器首先检查这个客户端请求里是否已包含了个session标识 - 称为 session id如果已包含个session id则介绍说明以前已经为此客户端创建过session服务器就按照session id把这个 session检索出来使用(如果检索不到可能会新建个)如果客户端请求不包含session id则为此客户端创建个session并且生成个和此session相关联session idsession id值应该是个既不会重复又不容易被找到规律以仿造这个 session id将被在本次响应中返回给客户端保存

  保存这个session id方式可以采用cookie这样在交互过程中浏览器可以自动按照规则把这个标识发挥给服务器般这个cookie名字都是类似于 SEEESIONID比如weblogic对于web应用生成cookieJSESSIONID= ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764名字就是 JSESSIONID

  由于cookie可以被人为禁止必须有其他机制以便在cookie被禁止时仍然能够把session id传递回服务器经常被使用种技术叫做URL重写就是把session id直接附加在URL路径后面附加方式也有两种种是作为URL路径附加信息表现形式为http://...../xxx; jsessionid= ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764

  另种是作为查询串附加在URL后面表现形式为http://...../xxx?jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764

  这两种方式对于用户来说是没有区别只是服务器在解析时候处理方式区别采用第种方式也有利于把session id信息和正常参数区分开来

  为了在整个交互过程中始终保持状态就必须在每个客户端可能请求路径后面都包含这个session id

  另种技术叫做表单隐藏字段就是服务器会自动修改表单添加个隐藏字段以便在表单提交时能够把session id传递回服务器比如下面表单

  <form name="testform" action="/xxx">
  <input type="text">
  </form>


  在被传递给客户端的前将被改写成

  <form name="testform" action="/xxx">
  <input type="hidden" name="jsessionid" value="ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764">
  <input type="text">
  </form>


  这种技术现在已较少应用笔者接触过很古老iPlanet6(SunONE应用服务器前身)就使用了这种技术

  实际上这种技术可以简单用对action应用URL重写来代替

  在谈论session机制时候常常听到这样种误解“只要关闭浏览器session就消失了”其实可以想象下会员卡例子除非顾客主动对店家提出销卡否则店家绝对不会轻易删除顾客资料对session来说也是除非通知服务器删除个session否则服务器会直保留般都是在用户做log off时候发个指令去删除session然而浏览器从来不会主动在关闭的前通知服务器它将要关闭因此服务器根本不会有机会知道浏览器已经关闭的所以会有这种错觉是大部分session机制都使用会话cookie来保存session id而关闭浏览器后这个 session id就消失了再次连接服务器时也就无法找到原来session如果服务器设置cookie被保存到硬盘上或者使用某种手段改写浏览器发出 HTTP请求头把原来session id发送给服务器则再次打开浏览器仍然能够找到原来session



  恰恰是由于关闭浏览器不会导致session被删除迫使服务器为seesion设置了个失效时间当距离客户端上次使用session时间超过这个失效时间时服务器就可以认为客户端已经停止了活动才会把session删除以节省存储空间

   5、理解javax.servlet.http.HttpSession

  HttpSession是Java平台对session机制实现规范标准它仅仅是个接口具体到每个web应用服务器提供商除了对规范标准支持的外仍然会有些规范标准里没有规定细微差异这里我们以BEAWeblogic Server8.1作为例子来演示

  首先Weblogic Server提供了系列参数来控制它HttpSession实现包括使用cookie开关选项使用URL重写开关选项session持久化设置session失效时间设置以及针对cookie各种设置比如设置cookie名字、路径、域 cookie生存时间等

  般情况下session都是存储在内存里当服务器进程被停止或者重启时候内存里session也会被清空如果设置了session持久化特性服务器就会把session保存到硬盘上当服务器进程重新启动或这些信息将能够被再次使用 Weblogic Server支持持久性方式包括文件、数据库、客户端cookie保存和复制

  复制严格说来不算持久化保存session实际上还是保存在内存里不过同样信息被复制到各个cluster内服务器进程中这样即使某个服务器进程停止工作也仍然可以从其他进程中取得session

  cookie生存时间设置则会影响浏览器生成cookie是否是个会话cookie默认是使用会话cookie有兴趣可以用它来试验我们在第 4节里提到那个误解

  cookie路径对于web应用来说是个非常重要选项Weblogic Server对这个选项默认处理方式使得它和其他服务器有明显区别后面我们会专题讨论

   6、HttpSession常见问题

   (在本小节中session含义为⑤和⑥混合)

   1、session在何时被创建

   个常见误解是以为session在有客户端访问时就被创建然而事实是直到某server端 HttpServletRequest.getSession(true)这样语句时才被创建注意如果JSP没有显示使用 关闭session则JSP文件在编译成Servlet时将会自动加上这样条语句 HttpSession session = HttpServletRequest.getSession(true);这也是JSP中隐含 session对象来历

   由于session会消耗内存资源因此如果不打算使用session应该在所有JSP中关闭它

   2、session何时被删除

   综合前面讨论session在下列情况下被删除a.HttpSession.invalidate;或b.距离上次收到客户端发送session id时间间隔超过了session超时设置;或c.服务器进程被停止(非持久session)

   3、如何做到在浏览器关闭时删除session

   严格做不到这可以做点努力办法是在所有客户端页面里使用javascript代码window.oncolose来监视浏览器关闭动作然后向服务器发送个请求来删除session但是对于浏览器崩溃或者强行杀死进程这些非常规手段仍然无能为力

   4、有个HttpSessionListener是如何回事

   你可以创建这样listener去监控session创建和销毁事件使得在发生这样事件时你可以做些相应工作注意是session创建和销毁动作触发listener而不是相反类似和HttpSession有关listener还有 HttpSessionBindingListenerHttpSessionActivationListener和 HttpSessionAttributeListener

   5、存放在session中对象必须是可序列化

   不是必需要求对象可序列化只是为了session能够在集群中被复制或者能够持久保存或者在必要时server能够暂时把session交换出内存在 Weblogic Serversession中放置个不可序列化对象在控制台上会收到个警告我所用过某个iPlanet版本如果 session中有不可序列化对象在session销毁时会有个Exception很奇怪

   6、如何才能正确应付客户端禁止cookie可能性

   对所有URL使用URL重写包括超链接formaction和重定向URL具体做法参见[6]

   http://e-docs.bea.com/wls/docs70/webapp/sessions.html#100770

   7、开两个浏览器窗口访问应用会使用同个session还是区别session

   参见第 3小节对cookie讨论对session来说是只认id不认人因此区别浏览器区别窗口打开方式以及区别cookie存储方式都会对这个问题答案有影响

   8、如何防止用户打开两个浏览器窗口操作导致session混乱

   这个问题和防止表单多次提交是类似可以通过设置客户端令牌来解决就是在服务器每次生成个区别id返回给客户端同时保存在session里客户端提交表单时必须把这个id也返回服务器首先比较返回id和保存在session里值是否如果不致则介绍说明本次操作已经被提交过了可以参看J2EE核心模式有关表示层模式部分需要注意是对于使用javascript window.open打开窗口般不设置这个id或者使用单独id以防主窗口无法操作建议不要再window.open打开窗口里做修改操作这样就可以不用设置

   9、为什么在Weblogic Server中改变session值后要重新次session.value

   做这个动作主要是为了在集群环境中提示Weblogic Server session中值发生了改变需要向其他服务器进程复制新session值

   10、为什么session不见了

   排除session正常失效原因的外服务器本身可能性应该是微乎其微虽然笔者在iPlanet6SP1加若干补丁Solaris版本上倒也遇到过;浏览器插件可能性次的笔者也遇到过3721插件造成问题;理论上防火墙或者代理服务器在cookie处理上也有可能会出现问题

   出现这问题大部分原因都是最常见就是在个应用中去访问另外个应用我们在下节讨论这个问题



   7、跨应用session共享

  常常有这样情况个大项目被分割成若干小项目开发为了能够互不干扰要求每个小项目作为个单独web应用开发可是到了最后突然发现某几个小项目的间需要共享些信息或者想使用session来实现SSO(single sign _disibledevent=>  HttpSession sessionA = (HttpSession)contextA.getAttribute("appA");



  值得注意是这种使用方法不可移植根据ServletContextJavaDoc应用服务器可以处于安全原因对于context.getContext("/appA");返回空值以上做法在Weblogic Server 8.1中通过

  那么Weblogic Server为什么要把所有应用cookie路径都设为/呢?原来是为了SSO凡是共享这个session应用都可以共享认证信息个简单实验就可以证明这修改首先登录那个应用描述符weblogic.xml把cookie路径修改为/appA 访问另外个应用会重新要求登录即使是反过来先访问cookie路径为/应用再访问修改过路径这个虽然不再提示登录但是登录用户信息也会丢失注意做这个实验时认证方式应该使用form浏览器和web服务器对basic认证方式有其他处理方式第 2次请求认证不是通过 session来实现具体请参看[7] secion 14.8 Authorization你可以修改所附举例来做这些试验

   8、整理总结

  session机制本身并不复杂然而其实现和配置上灵活性却使得具体情况复杂多变这也要求我们不能把仅仅某经验或者某个浏览器服务器经验当作普遍适用经验而是始终需要具体情况具体分析
0

相关文章

读者评论

发表评论

  • 昵称:
  • 内容: