深入理解asp.net SessionState


深入理解asp.net SessionState
2010年06月06日
  web Form 网页是基于HTTP的,它们没有状态, 这意味着它们不知道所有的请求是否来自
  同一台客户端计算机,网页是受到了破坏,以及是否得到了刷新,这样就可能造成信息的
  丢失。 于是, 状态管理就成了开发网络应用程序的一个实实在在的问题。
  在ASP中能够通过Cookie 、查询字符串、 应用程序、会话(Session) 等轻易解决这些问题。
  现在在ASP.NET环境中,我们依然可以使用这些功能,并且功能更加强大。
  状态管理分为服务端和客户端两种情况, 这里只是介绍 服务端状态管理: 
  与Application对象不同的是, ASP.NET 的Session对象可以在IIS服务器或者工作进程重新启动时
  恢复启动前的状态而不丢失其中的数据。这是因为存储在Session中的所以信息都缺省的存储在
  一个作为Windows服务运行的状态服务器进程中。状态可以被序列化并以二进制形式保存在内存中。
  程序员可以悬着使用Microsoft Sql server数据库来存储数据。
  状态服务器服务和状态信息可以和web应用程序一起存在于同一台服务器上,也可以保存到外部的
  状态服务器上。 为了指定如何存储信息,程序员可以在web.config文件中编写适当的配置。
  ASP.NET会话状态模块在Web.config文件中标记下的标记的mode属性来决定
  该属性的四种可能的值: Off、 Inproc StateServer 和SQLserver。
  1 Inproc是缺省的设置
  InProc(默认,进程内的会话状态):Session存储在IIS进程中(Web服务器内存)。如果使用的是Windows 2000 Server或Windows XP,IIS使用aspnet_wp.exe进程,如果使用的是Windows 2003 Server,IIS使用w3wp.exe。 
  InProc拥有最好的性能。但进程内Session很容易丢失Session信息。如果重启了应用程序,所有的Session信息就会丢失。而很多原因都会导致ASP.NET应用程序的重启。 
  修改了Web.Config或Global.asax文件,或改变了文件的修改日期。 
  修改了\bin或\App_Code目录里的文件。 
  防病毒软件修改了上述文件等等
  它允许"无Cookie"的会话,以及在服务器之外存储
  会话数据。ASP.NET会话状态模块在Web.config文件中像下面这样配置:
  
  在这个例子中,mode属性设为InProc(默认值),表明会话状态要由ASP.NET存储到内存中,而且
  不用Cookie来传递会话ID。相反,会话ID要直接插入一个网页URL的查询字符串中。例如,采用
  InProc模式并建立一个会话之后,调用一个假想的ASP.NET网页时,需要采用下面这样的URL:
  http://my.website.com/(12mfju55vgblubjlwsi4dgjq)/e ducation.aspx
  圆括号中长长的字母、数字字符串就是会话ID。ASP.NET引擎从查询字符中提取会话ID,并将用户
  请求与特定会话联系起来。采取这种方式,不管Cookie还是隐藏表单字段都用不着了。
  所以,即使网页中没有使用表单,也能加入会话。
  但是这种方法,应用程序的状态将依赖于 ASP.NET进程, 当IIS进程崩溃或者正常重启时,保存在
  进程中的状态将丢失。
  2 mode属性设为Off
  和从前的ASP一样,ASP.NET的会话状态管理是要产生开销的。所以,假如某个网页不需要访问
  Session对象,开发者应将那个页的Page预编译指令的EnableSessionState属性设为False。
  要为整个网站禁用会话状态,可在Web.config文件中将sessionState元素的mode属性设为Off。
  为了克服inproc 模式的缺点, ASP.NET 提供了两种进程外保存会话状态的方法。
  3 StateServer会话管理
  将mode属性设为StateServer,也就是将会话数据存储到单独的内存缓冲区中,再由单独一台机器上运行
  的Windows服务来控制这个缓冲区。状态服务全称是"ASP.NET State Service "(aspnet_state.exe),
  它由Web.config文件中的stateConnectionString属性来配置。该属性指定了服务所在的服务器,以及要监
  视的端口:
  
  在这个例子中,状态服务在一台名为myserver的机器的42424端口(默认端口)运行。要在服务器上改变
  端口,可编辑HKLM\SYSTEM\CurrentControlSet\Services\aspnet_stat e注册表项中的Port值。
  显然,使用状态服务的优点在于进程隔离,并可在Web farm中共享。 使用这种模式,会话状态的存储将不
  依赖于iis进程的失败或者重启,然而,一旦状态服务中止,所有会话数据都会丢失。换言之,状态服务不
  像SQL Server那样能持久存储数据;它只是将数据存储在内存中。
  4 用SQL Server进行会话管理 
  ASP.NET还允许将会话数据存储到一个数据库服务器中,方法是将mode属性变成SqlServer。 
  在这种情况下,ASP.NET尝试将会话数据存储到由sqlConnectionString属性(其中包含数据源以及登录服
  务器所需的安全凭证)指定的SQL Server中。
  为了用恰当的数据库对象来配置SQL erver,管理员还需要创建ASPState数据库,
  方法是运行WinDir\Microsoft.Net\Framework\Version文件夹中的InstallState.sql脚本(WinDir是服务
  器的Windows文件夹,而Version是你使用的.NET框架版本的安装文件夹)。
  要配置SQL服务器,可以在命令行中运行SQL Server 提供的命令行工具osql.exe
  osql -S [ server name] -U [user] -P [password] 如何和SQL Server配合实现状态管理的。
  卸载这些表和存储过程,可以使用UninstallSqlState.sql脚本,使用方法与上面类似。
  做好必要的数据库准备工作后,将web.config 文件中的sessionstate 元素的mode改为"sqlserver"
  ,并且指定SQL连接字符串。具体如下:
  mode="sqlserver"
  sqlConnectionString="data source=127.0.0.1; userid=sa; password="
  配置好SQL Server后,应用程序代码运行时就和InProc模式没有什么区别。但要注意的是,由于数据不存
  储在本地内存,所以存储会话状态的对象需要进行序列化和反序列化,以便通过网络传给数据库服务器,
  以及从数据库服务器传回。这当然会影响性能。通过在数据库中存储会话状态,可分别针对扩展性及可靠
  性来有效地平衡性能。另外,可以利用SQL Server的集群,使状态存储不依赖于单个的SQL Server, 
  这样就可以为应用程序提供极大限度的可靠性。
   1.理解Session State模式
   存储位置
  InProc:session在服务器中以活动对象方式存储(aspnet_wp.exe)
  StateServer: session被序列化并保存在单独的aspnet_state.exe的内存中。StateServer能够运行在另一台服务器上
  SQLServer: session被序列化并保存在SQL Server中
  性能:
  InProc:最快,但是session数据越多,web服务器上消耗的内存也越多,它可能影响性能。
  StateServer:当存储基本类型(如string,integer等)数据时,在同一个测试环境中它比InProc慢15%。如果你存储大量对象,序列化和反序列化可能影响到性能
  SQLServer:当存储基本类型(如string,integer等)数据时,在同一个测试环境中它比InProc慢25%。它也有与StateServer一样的序列化性能问题。
   关于Out-of-Proc(OOP,非InProc)模式的性能提示
  如果你使用OOP模式(即StateServer或SQLServer),session state中的序列化和反序列化对象将成为你的主要性能消耗之一。对于基本类型,ASP.NET通过一种内部优化方法来完成序列化和反序列化。(基本类型包括所有的数字类型(如Int, Byte, Decimal,String, DateTime, TimeSpan, Guid, IntPtr和UIntPtr等))
  如果你有一个session变量(如一个ArrayList对象),且它不是一个基本类型,ASP.NET将使用BinaryFormatter来进行序列化和反序列化,那可能会相对慢一些。
  所以出于性能考虑,最好使用上面列出的基本类型来存储所有的session state数据。例如,如果你需要存储两个东西,名字和地址,在session state中你既可以(方法a)使用两个string session变量来存储它们,也可以(方法b)创建一个内含两个string的类来保存它们,然后把这个类对象保存在一个session变量中。出于性能考虑,你应该选择方法a。
  为了进一步理解这个主题,请看FAQ中的一个问题:"序列化和反序列化如何在SqlServer和StateServer模式下工作"
   健壮性
  InProc:如果工作者进程(aspnet_wp.exe)进行资源回收或者应用程序域(appdomain)重启动,session state就会丢失。这是因为session state是保存在一个应用程序域的内存空间中的。对配置文件(如web.config和machine.config)的修改或者\bin目录的任何改变(例如在你使用VS编译应用程序后产生了一个新的dll)都可能引起重启动,详细请见KB324772。在1.0中,也有一个bug可能引起工作者进程重启动,但这个bug在1.1中已经修复,见KB321792。
  如果你使用的是IIS6.0,你可以在IIS Manager中找到Application Pools/DefaultAppPool,其中可以看到回收(Recycling)选项卡与性能(Performace)选项卡中是否有引起IIS工作者进程(w3svc.exe)停止工作的参数。
  更多有关应用程序资源回收的内容,可以看我的另一篇FAQ:
  http://www.asp.net/Forums/ShowPost.aspx?tabindex=1 &PostID=232621
  StateServer:解决了InProc模式的session state丢失问题。允许一个webfarm在中央服务器中存储session。只能在State Server上出现失败。
  SQLServer:与StateServer相似。session state的数据在SQL Server重启后仍然保留着,你也可以按照KB311209的步骤使用SQL server failover cluster
   警告
  InProc:它不能在web garden模式下工作,因为在这个模式下会有多个aspnet_wp.exe在同一台机器上运行。建议在使用web garden使切换到State Server或SQL Server。仅在InProc模式下支持Session_End事件。
  StateServer
  - 在web farm中,请确认在所有的web服务器上有相同的。KB313091描述了如何设置它。
  - 请确保你的对象是可序列化的。详见KB312112
  - 为了在web farm中的不同web服务器上维护session state,IIS Metabase中的网站应用程序路径(如\LM\W3SVC\2)应该在所有的服务器上保持一致(大小写敏感)。详见KB325056
  SQLServer
  - 在1.0中有一个bug,如果你在连接字符串中指定integrity security(如"trusted_connection=true"或 "integrated security=sspi"),且你打开了asp.net的身份模拟,它将不会工作。这个问题在KB324479中有描述,不幸的是这份文档中的描述和原因部分是错误的。不过已经有一个QFE fix对它作了修复,这个fix将包含在1.0 sp3中。这个问题在1.1中已经修复了。
  - 请确认你的对象是可序列化的,否则你的请求可能被挂住,详见KB312112。SQLServer模式的挂起问题已经在1.1中修复,KB324479的QFE fix也修复了这个问题。1.0 sp3也对这个问题作了修复。
  - 为了在web farm中的不同web服务器上维护session state,IIS Metabase中的网站应用程序路径(如\LM\W3SVC\2)应该在所有的服务器上保持一致(大小写敏感)。详见KB325056 
   其他资源
  http://msdn.microsoft.com/library/default.asp?url= /library/en-us/dnaspp/html/aspnetsessionstate.asp
  http://msdn.microsoft.com/library/default.asp?url= /library/en-us/dnbda/html/CachingArchch2.asp
  http://www.411asp.net/home/tutorial/specific/web/s essions
  2. FAQ问题列表
  Q: session state在部分浏览器上工作,而在其他一些上不工作。为什么呢?
  Q: 在InProc模式中,为什么我有时会丢失所有的session?
  Q: session state在一些web服务器上工作,但是在其他服务器上不工作。
  Q: 为什么session state不可用?
  Q: 为什么session_end没有触发?
  Q: 使用InProc模式时,为什么我的session变量频繁丢失?
  Q: 在session超时或删除之后,为什么SessionID保持不变
  Q: 为什么SessionID每一次请求都会改变
  Q: Session.Abandon()和Session.Clear()有什么区别
  Q: session的Timeout属性是一个滑动超时值吗?
  Q: 我可以在ASP.NET和ASP之间共享session吗?
  Q: 我可以在web应用程序(例如虚拟目录或者IIS的应用程序)间共享session state吗?
  Q: 在session state中可以存储哪些类型的对象?
  Q: 为什么我的请求在切换到SQLServer模式之后挂住了?
  Q: 为什么Response.Redirect和Server.Transfer在Session_End中不工作?
  Q: 在Session_End中,我可以获得一个有效的HttpSessionState对象和HttpContext对象吗?
  Q: 在web service中如何使用session?
  Q:我正在写一个HttpHandler,为什么session stae不工作?
  Q: 我正在使用web farm,并且每当我重定向到其他服务器时,session state就会丢失?
  Q: 如果使用cookieless,我该如何从一个HTTP页面重定向到一个HTTPS页面?
  Q: session state有没有一个锁机制来安排对session的访问顺序?
  Q: 我该如何检测一个session过期,然后重定向到另一个页面
  Q: 在Session_End中,我尝试使用SQL做一些清理工作,但是失败了,请问为什么?
  Q: 我使用的是SQLServer模式,为什么我的session不会过期
  Q: 我有一个以htm为扩展名的frameset页面,并且我发觉其中包含的每个帧在第一次请求时都有一个不同的SessionID,这是为什么?
  Q: 我将EnableSessionState设置为ReadOnly,但是在InProc模式下,我仍然可以修改session,为什么?
  Q: 我将cookieless设置为true,在Redirect之后session变量丢失了,为什么?
  Q: 将cookieless设置为true有哪些缺点
  Q: 在InProc模式下,我用编程方式改变了session的超时时间,它触发了Session_End,为什么?
  Q: 在SQLServer模式下,我可以把session state保存在除tempdb之外的数据库中吗?
  Q: 如何防止将未加密的字符串放在我的连接字符串汇总?
  Q: 在使用SQLServer模式时,我需要怎样的SQL权限?
  Q: 我可以自己写定制的session state模式吗?
  Q: 在SQLServer或StateServer模式下,序列化和反序列化如何工作?
  Q: 我该如何让我的state server更安全?
  Q: 我能否可以使用非global.asax中的处理程序来订阅SessionStateModule.End事件?
  Q: 不同的应用程序可以把他们的session state保存在同一个SQL Server上的不同数据库中吗?
   Q: session state在部分浏览器上工作,而在其他一些上不工作。为什么呢?
  A: 估计你没有使用cookieless,你必须保证你的浏览器支持cookie。请参考这份KB:http://support.microsoft.com/default.aspx?scid=kb; EN-US;q316112
   Q: 在InProc模式中,为什么我有时会丢失所有的session? 
  A: 请见理解session state模式的健壮性部分
   Q: session state在一些web服务器上工作,但是在其他服务器上不工作。
  A: 可能是机器名的问题,见http://support.microsoft.com/default.aspx?scid=kb; EN-US;q316112
   Q: 为什么session state不可用?
  A: 
  - 首先,检查web.config、machine.config和Page标签来确认你启用了session state
  参考资料:
  http://msdn.microsoft.com/library/default.asp?url= /library/en-us/cpguide/html/cpconsessionstate.asp
  http://msdn.microsoft.com/library/default.asp?url= /library/en-us/cpgenref/html/cpconpage.asp
  - 请注意session state并非在任何地方、任何时间都可以使用,它仅在HttpApplication.AcquireRequestState事件之后可用。例如,在 global.asax中的Application_OnAuthenticateRequest处理程序中,session state不可用
  - 请确认System.Web.SessionState.SessionStateModule已包含在配置文件的节中。一个常见的例子是,出于性能考虑,SharePoint应用程序会把这个模块从web.config文件中移除,因此导致session不可用
   Q: 为什么session_end没有触发?
  A: 这是最常见的问题之一
  1. 请记住session_end仅在InProc模式中可用
  2. 关闭浏览器,session_end是不会触发的。HTTP是一种无状态协议,服务器没有办法知道你的浏览器是否已经关闭。
  3. 当有n分钟(n=timeout值)的无操作或调用Session.Abandon时,Session_End才会触发
  4. 对于情况1而言,Session_End将由一个后台线程触发,这表示:
  a. Session_End中的代码使用工作者进程账号运行,如果你访问如数据库这样的资源时,可能会有权限问题。
  b. 如果在Session_End中发生错误,程序不会通知发生了什么
  5. 对于情况2而言,为了让Session_End触发,session state必须先存在。这意味着你必须在session state中存储一些数据,并且已经完成了至少一个请求
  6. 还是对于情况2而言,Session_End仅在被丢弃的session被找到的时候才会触发。这样的话,如果你在同一个请求中创建并丢弃一个 session,由于session没有被保存,因此也不会被找到,Session_End将不会被调用。这是v1.0和v1.1中的bug。
   Q: 使用InProc模式时,为什么我的session变量频繁丢失?
  A: 有可能是应用程序资源回收引起的,见http://support.microsoft.com/default.aspx?scid=kb; en-us;Q316148
  在v1.0中有一个bug可能会导致工作者进程重启动。在v1.1和v 1.0sp2中已经修复。见http://support.microsoft.com/default.aspx?scid=kb; EN-US;321792
  关于应用程序资源回收的详细信息,请见我的另一篇:FAQhttp://www.asp.net/Forums/ShowPost.aspx?tabindex=1 &PostID=232621
   Q: 在session超时或删除之后,为什么SessionID保持不变
  A: 尽管在超时周期之后session state过期,sessionID将一直保持到浏览器session过期为止,也就是说,一个相同的sessionID可以有多次session超时,但是始终对应着一个相同的浏览器实例。
   Q: 为什么SessionID每一次请求都会改变
  A: 如果你的应用程序从未在session state中存储过数据。在这种情况下,那么每次请求都会创建一个新的session state(ID也是新的),但是不会被存储,因为里面什么数据都没有。
  尽管如此,有两种例外可能产生相同的Session ID
  - 如果用户使用相同的浏览器实例来请求另一个使用session state的页面,那么你每次获得的Session ID是相同的。详见"在session超时或删除之后,为什么SessionID保持不变?"
  - 如果使用了Session_OnStart事件,即使session为空,asp.net也会保存session state。
   Q: Session.Abandon()和Session.Clear()有什么区别
  A: 主要的区别在于,如果你调用Session.Abandon(), Session_End将被触发(仅在InProcxi下适用),在下一个请求中,Session_Start触发。而Session.Clear()仅仅是清除数据,但没有删除session。
  Q: session的Timeout属性是一个滑动超时值吗?
  A: Session的Timeout是一个滑动过期时间,意思是一旦你的页面访问session state,过期时间就会向挪。注意,只要页面没有被禁用,在请求时页面就会自动访问session
  Q: 我可以在ASP.NET和ASP之间共享session吗?
  A:不可以。但是有一篇文章讲到了如何来绕过这个问题:http://www.msdn.microsoft.com/library/default.asp? url=/library/en-us/dnaspp/html/ConvertToASPNET.asp
  当然也有一些第三方解决方案。
  Q: 我可以在web应用程序(例如虚拟目录或者IIS的应用程序)间共享session state吗?
  A:不能。
  Q: 在session state中可以存储哪些类型的对象?
  A:这是由你使用的模式决定的
  - 如果你使用的是InProc模式,存储在session state中的对象是活对象,那么你就可以存储你创建的任何对象
  - 如果你使用的是SQLServer或State Server模式,当处理一个请求时,session state中的对象对象将被序列化和反序列化,所以请确认你的对象都是可序列化的,而它们的类都作了可序列化标记。如果没有,session state将不会成功存储。在v1.0中,有一个bug,当这个问题发生时,如果使用SQLServer模式,请求可能在不知情的情况下被挂起。挂起的问题在v1.1和v1.0 sp3中已经修复。KB324479的QFE fix也包含了对这一问题的修复。
  更多信息请见:http://support.microsoft.com/directory/article.asp ?ID=KB;EN-US;q312112
  Q: 为什么我的请求在切换到SQLServer模式之后挂住了?
  A:请看问题"在session state中可以存储哪些类型的对象?"的答案
  Q: 为什么Response.Redirect和Server.Transfer在Session_End中不工作?
  A:Session_End是在服务器内部触发的,它基于一个内部的计时器。因此,在事件触发时,与任何HttpRequest对象无关。这也是为什么Response.Redirect 和Server.Transfer不工作的原因。
  Q: 在Session_End中,我可以获得一个有效的HttpSessionState对象和HttpContext对象吗?
  A:  你可以获得httpSessionState对象,你可以使用'Session'来访问该对象。但是你无法访问HttpContext,因为这个事件和请求没有任何关系。
   Q: 在web service中如何使用session?
  A: 需要在调用方使用一些技巧,你必须保存web服务使用的cookie。请见关于HttpWebClientProtocol.CookieContainer的MSDN文档。
  尽管如此,如果你是通过代理对象从你的页面调用web服务,由于架构限制,web服务和你的页面无法共享session state。
  如果你通过redirect调用web服务,这是可以完成的 Q:我正在写一个HttpHandler,为什么session stae不工作? A: 你的HttpHandler接口必须实现标记接口IRequiresSessionState或IReadOnlySessionState,方能使用session state。
   Q: 我正在使用web farm,并且每当我重定向到其他服务器时,session state就会丢失?
  A: 为了在web farm中的不同服务器之间维护session state,IIS Metabase中的网站应用程序路径(例如 \LM\W3SVC\2)应该在所有的web服务器上保持一致(大小写敏感)。详见KB325056
   Q: 如果使用cookieless,我该如何从一个HTTP页面重定向到一个HTTPS页面?
  A: 尝试使用下面的代码:
  String originalUrl = "/fxtest3/sub/foo2.aspx";
  String modifiedUrl = "https://localhost" + Response.ApplyAppPathModifier(originalUrl);
  Response.Redirect(modifiedUrl);
   Q: session state有没有一个锁机制来安排对session的访问顺序?
  A:session state实现了读写锁定机制:
  - 对session state有写权限(如 )的页面或帧将获得这个session的写锁,直到请求结束。
  - 对session state有读权限(如 )的页面或帧将获得这个session的读锁,直到请求结束。 
  - 读锁会阻塞写锁;读锁不会阻塞读锁;写锁会阻塞所有的读锁和写锁
  - 这也是为什么当两个帧同时拥有session的访问权限时,一个帧必须等待另一帧先完成
   Q: 我该如何检测一个session过期,然后重定向到另一个页面
  A: 这是经常要遇到的问题,但不幸的是没有很简单的方法来完成它。我们将期待在一个主要版本中实现它。同时,如果你使用cookie,你可以在cookie中存储一个标志,这样你就可以区分新浏览器+新session及旧浏览器+过期session,下面的代码在session过期时会重定向到一个过期页面。
  void Session_OnStart(Object sender, EventArgs e) { 
  HttpContext context = HttpContext.Current;
  HttpCookieCollection cookies = context.Request.Cookies; 
  if (cookies["starttime"] == null) { 
  HttpCookie cookie = new HttpCookie("starttime", DateTime.Now.ToString()); 
  cookie.Path = "/"; 
  context.Response.Cookies.Add(cookie); 
  } 
  else { 
  context.Response.Redirect("expired.aspx"); 
  } 
  } 
   Q: 在Session_End中,我尝试使用SQL做一些清理工作,但是失败了,请问为什么?
  A: 首先,session_End仅在InProc模式下支持。
  第二,Session_End是用运行工作者进程(aspnet_wp.exe)的帐号运行的,这个账号可以在machine.config中指定。因此,在你的Session_End中,如果使用integrity security连接SQL,它将使用工作者进程账号身份连接,这可能会引起登录失败,这要看你的SQL安全设置了。
   Q: 我使用的是SQLServer模式,为什么我的session不会过期
  A: 在SQLServer模式下,session过期是由SQL Agent使用一个注册任务完成的,请确认你的SQL Agent是否已经运行。
   Q: 我有一个以htm为扩展名的frameset页面,并且我发觉其中包含的每个帧在第一次请求时都有一个不同的SessionID,这是为什么?
  A: 原因是你的frameset页面是一个htm文件而不是一个aspx页面
  在通常情况下,如果一个frameset页为一个aspx文件,当你请求该页面时,会首先发请求给web服务器,你会收到一个asp.net session cookie(其中保存着session id),然后浏览器会为frame发送一个单独的请求,而每个请求将拥有相同的session id。
  然而,因为你的页面是一个htm文件,第一个请求就不会获得任何session cookie,因为页面是由asp处理的而非asp.net,然后浏览器会为每个帧发送单独的请求。但是,这次每个单独的请求将不会持有任何 session id,这样的话每个帧将创建自己的session。这也是为什么你在每个帧中看到的session id都不同。最后一个请求将赢得胜利,因为它将覆盖前两个请求写入的cookie。如果你刷新一次,你将看到它们拥有了相同的session id。
  这个行为是设计所决定的,简单的解决方法就是将frameset页面改称aspx
   Q: 我将EnableSessionState设置为ReadOnly,但是在InProc模式下,我仍然可以修改session,为什么?
  A: 尽管那些EnableSessionState被设置为ReadOnly,但是在InProc模式中,用户仍然可以修改session。唯一的区别在于session在请求中不会被锁住,这一限制是设计所决定的。对于这一点没有在msdn中提到我表示抱歉。
   Q: 我将cookieless设置为true,在Redirect之后session变量丢失了,为什么?
  A: 如果你使用的是cookieless,你必须使用相对路径(如..\hello.aspx),而不是绝对路径(如\foo\bar\hello.aspx)。如果你使用的是绝对路径,ASP.NET不会将session id保存在url中。
   Q: 将cookieless设置为true有哪些缺点
  A: 设置cookieless=true表示一些潜在的规则,主要有:
  1. 你不能在你的页面中使用绝对路径
  2. 在http和https之间切换的话,你必须做一些额外的动作
  3. 如果你的客户发送了一个链接到一个朋友,URL将包含session id,两个用户可以在同一时间使用相同的session id
   Q: 在InProc模式下,我用编程方式改变了session的超时时间,它触发了Session_End,为什么?
  A: 这是InProc的一个bug。如果你更改session的timeout值为另一个值,Session_End将被调用(但不会调用Session_Start)。我们期待在v2.0中能够修复这个错误。
   Q: 在SQLServer模式下,我可以把session state保存在除tempdb之外的数据库中吗?
  A: 是的。见KB311209。
   Q: 如何防止将未加密的字符串放在我的连接字符串汇总?
  A: 见sql trusted connection或者将连接字符串以加密数据形式保存在注册表中。详情请见,KB329250和KB329290。
   Q: 在使用SQLServer模式时,我需要怎样的SQL权限?
  A: 调用者需要对下面的存储过程拥有EXEC权限,
  dbo.TempGetAppID
  dbo.TempGetStateItem
  dbo.TempGetStateItemExclusive
  dbo.TempReleaseStateItemExclusive
  dbo.TempInsertStateItemLong
  dbo.TempInsertStateItemShort
  dbo.TempUpdateStateItemLong
  dbo.TempUpdateStateItemShort
  dbo.TempUpdateStateItemShortNullLong
  dbo.TempUpdateStateItemLongNullShort
  dbo.TempRemoveStateItem
  dbo.TempResetTimeout 
  在v1.1中,你也需要对下面的存储过程拥有EXEC权限
  dbo.TempGetStateItem2
  dbo.TempGetStateItemExclusive2
  请注意存储过程的拥有者必须对session state表(dbo.ASPStateTempSessions和 dbo.ASPStateTempApplications)拥有SELECT/INSERT/UPDATE/DELETE 权限。通常,拥有者是执行installsqlstate.sql(或者持久版本,见KB311209)的帐号来安装sql session state需要的表、存储过程、数据库
  也请注意,如果你的session state表在tempdb中(默认情况下)如果你对SQL Server进行资源回收,所有在这张表上的权限设置将丢失。
  Q: 我可以自己写定制的session state模式吗?
  A:(待翻译)
  Q: 在SQLServer或StateServer模式下,序列化和反序列化如何工作?
  A: (待翻译) 
   Q: 我该如何让我的state server更安全?
  A:如果state server和web server运行在一台机器上,通过设置HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Servic es\ aspnet_state\Param ters\AllowRemoteConnection的dword项为0,可以让state server仅在本地运行。这样就可以防止远程客户端连见到state server上。这一特性在v1.1中可用,在v1.0 sp3中也有。
  state server必须受防火墙保护,以防止外部连接以保证真正安全。默认的端口是TCP 42424,你可以设置HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Servic es\ aspnet_state\Param ters\Port来改变它。如果是本地模式,除了127.0.0.1以外,屏蔽所有外来连接;如果是远程模式,显式的禁用所有的地址,除了对wev服务器的连接。
  使用IPSec是另一种保护state server的方式。
   Q: 我能否可以使用非global.asax中的处理程序来订阅SessionStateModule.End事件?
  A: 答案是否定的。当SessionStateModule触发End事件时,只有定义在global.asax中的方法才会被触发
  这是出于安全原因考虑的才对此进行限制。假设asp.net允许用户使用的其他的处理程序来处理End事件。在这种情况下,用户通常使用一个页面方法作为处理程序,当你在事件订阅时传入处理程序,处理程序将与你的程序运行在的HttpApplication实例关联。请注意, HttpApplication实例会被回收来处理其他请求。这样的话,当End事件触发时,asp.net将调用处理程序,而与之关联的 HttpApplication实例已经被另一个请求所使用,这样的情况将引发各种各样的问题。为了避免这种危险,在v1.0中决定进调用 Global.asax中定义的方法。希望你们都可以忍受这一限制。
   Q: 不同的应用程序可以把他们的session state保存在同一个SQL Server上的不同数据库中吗?
  A: 答案是肯定的。详情请见:http://support.microsoft.com/default.aspx?scid=kb; EN-US;836680
  原文地址:http://forums.asp.net/7504/ShowPost.aspx  译者:Tony Qu (来自BluePrint翻译团队)
  原文最后一次更新:2004年9月21日

猜你喜欢

转载自chh58chh.iteye.com/blog/1361983
今日推荐