1、ASP.NET 会话状态
2、会话状态模式
3、ASP.NET在不同应用程序之间共享Session
4、Session无故丢失
5、客户端使用Cookieless的方式存储Session信息
6、Session.SessionID 固定
1、ASP.NET 会话状态
会话状态可在以下情况下使用:存储特定于单独会话的短期信息,并且需要较高的安全性。不要在会话状态中存储大量的信息。需要注意,将为应用程序中每一会话的生存期创建并维护会话状态对象。在支持许多用户的应用程序中,这可能会占用大量服务器资源并影响可缩放性。*p1
ASP.NET 默认情况下将会话信息存储在 ASP.NET 应用程序的内存空间。您可以使用一个独立的服务存储会话信息以便重新启动 ASP.NET 应用程序后会话信息仍然保留;或将会话信息存储在 SQL Server 中以便会话信息可供网络场中的多个 Web 服务器使用(重新启动 ASP.NET 应用程序后会话信息也会保留);或将会话信息存储在自定义数据存储区。有关更多信息,请参见会话状态模式。
除了会话状态外,ASP.NET 还提供在应用程序中保留数据的一些其他方式。有关每种方式的比较,请参见 ASP.NET 状态管理建议。*p2
注:
*p1:ASP.NET 状态管理建议 http://msdn.microsoft.com/zh-cn/library/z1hkazw7(v=VS.80).aspx
*p2:ASP.NET 会话状态 http://msdn.microsoft.com/zh-cn/library/87069683(v=VS.80).aspx
2、会话状态模式
ASP.NET 会话状态支持若干用于会话数据的存储选项。每个选项都由 SessionStateMode 枚举中的一个值标识。下面的列表描述了可用的会话状态模式:
- InProc 模式,此模式将会话状态存储在 Web 服务器上的内存中。这是默认设置。注意:它是唯一支持 Session_OnEnd 事件的模式。
- StateServer 模式,此模式将会话状态存储在一个名为 ASP.NET 状态服务的单独进程中。这确保了在重新启动 Web 应用程序时会保留会话状态,并让会话状态可用于网络场中的多个 Web 服务器。注意:如果模式设置为 StateServer,则存储在会话状态中的对象必须是可序列化的。
- SQLServer 模式,将会话状态存储到一个 SQL Server 数据库中。这确保了在重新启动 Web 应用程序时会保留会话状态,并让会话状态可用于网络场中的多个 Web 服务器。注意:如果是 SQL Server 模式,则存储在会话状态中的对象必须是可序列化的。
- Custom 模式,此模式允许您指定自定义存储提供程序。
- Off 模式,此模式禁用会话状态。
通过在应用程序的 Web.config 文件中为 sessionState 元素的 mode 属性分配一个 SessionStateMode 枚举值,可以指定要让 ASP.NET 会话状态使用的模式。除了 InProc 和 Off 之外,其他模式都需要附加参数,例如将在本主题后面讨论的连接字符串值。通过访问 System.Web.SessionState.HttpSessionState.Mode 属性的值,可以查看当前选定的会话状态。*p3
注:
*p3:会话状态模式 http://msdn.microsoft.com/zh-cn/library/ms178586(v=VS.80).aspx
3、ASP.NET在不同应用程序之间共享Session *p4
多个单独的应用程序,如何将这些模块集中身份验证与授权过程
方案1:
将每个独立的Web应用程序放到统一的解决方案中,实现起来复杂,易用性不高。
方案2:利用Session会话共享
InProc模式,Session被存储在IIS进程中,每个虚拟目录是隔离的,所以无法共享Session。
StateServer 模式,虽然是独立的状态服务器(进程),但在内存中这些应用程序还是隔离的。
SQLServer 模式,由于对Session的全部操作都是由存储过程来实现的,而且存储过程未进行加密,可以通过修改存储过程的内部结构来达到共享的目的。
ASPState数据库ASPStateTempApplications表中存储的是应用程序信息,每个应用程序在启动的时候在这里会注册一条记录,包括应用程序的ID(通过哈希算法生成的)和应用程序名称。有多少个应用程序,在这个表里就对应多少条记录。那我们现在要做的是把这些记录变成一条记录,也就是要欺骗Framework,让它认为这些不同的应用程序是同一个应用程序。
TempGetAppID存储过程,这个存储过程是用于通过传递应用程序名称来得到应用程序ID信息的。每个应用程序在调用这个过程时,这个过程会去AspStateTempApplications中检查是否有相应的记录,如果没有,就插入记录,然后返回相应的ID。
ALTER PROCEDURE [dbo].[TempGetAppID]
@appName tAppName,
@appId int OUTPUT
AS
SET @appName = LOWER(@appName)
--变量值固定,使所有应用程序通用为一个
SET @appName = '/lm/w3svc/650056020/root/personnel/share'
SET @appId = NULL
SELECT @appId = AppId
FROM [tempdb].dbo.ASPStateTempApplications
WHERE AppName = @appName
注:
*p4:ASP.NET在不同应用程序之间共享Session http://www.3qsoft.com/Article.aspx?ID=173
4、Session无故丢失 *p5
mode="InProc"
==
默认的配置方式很容易丢失Session 请参考
asp中Session的工作原理:
asp的Session是具有进程依赖性的。ASP Session状态存于IIS的进程中,也就是inetinfo.exe这个程序。所以当inetinfo.exe进程崩溃时,这些信息也就丢失。另外,重起或者关闭IIS服务都会造成信息的丢失。
原因1:
bin目录中的文件被改写,asp.net有一种机制,为了保证dll重新编译之后,系统正常运行,它会重新启动一次网站进程,这时就会导致Session丢失,所以如果有access数据库位于bin目录,或者有其他文件被系统改写,就会导致Session丢失
原因2:
文件夹选项中,如果没有打开“在单独的进程中打开文件夹窗口”,一旦新建一个窗口,系统可能认为是新的Session会话,而无法访问原来的Session,所以需要打开该选项,否则会导致Session丢失
原因3:
似乎大部分的Session丢失是客户端引起的,所以要从客户端下手,看看cookie有没有打开
原因4:
Session的时间设置是不是有问题,会不会因为超时造成丢失
原因5:
IE中的cookie数量限制(每个域20个cookie)可能导致session丢失
原因6:
使用web garden模式,且使用了InProc mode作为保存session的方式
解决丢失的经验
1. 判断是不是原因1造成的,可以在每次刷新页面的时候,跟踪bin中某个文件的修改时间
2. 做Session读写日志,每次读写Session都要记录下来,并且要记录SessionID、Session值、所在页面、当前函数、函数中的第几次Session操作,这样找丢失的原因会方便很多
3. 如果允许的话,建议使用state server或sql server保存session,这样不容易丢失
4. 在global.asa中加入代码记录Session的创建时间和结束时间,超时造成的Session丢失是可以在SessionEnd中记录下来的。
5. 如果有些代码中使用客户端脚本,如javascript维护Session状态,就要尝试调试脚本,是不是因为脚本错误引起Session丢失
问:为什么Session在有些机器上偶尔会丢失?
答:可能和机器的环境有关系,比如:防火墙或者杀毒软件等,尝试关闭防火墙。
问:为什么当调用Session.Abandon时并没有激发Session_End方法?
答:首先Session_End方法只支持InProc(进程内的)类型的Session。其次要激发Session_End方法,必须存在Session(即系统中已经使用Session了),并且至少要完成一次请求(在这次请求中会调用该方法)。
问:为什么当我在InProc模式下使用Session会经常丢失?
答:该问题通常是由于应用程序被回收导致的,因为当使用进程内Session时,Session是保存在aspnet_wp进程中,当该进程被回收Session自然也就没有了,确定该进程是否被回收可以通过查看系统的事件查看器获得信息。
具体信息请参考:
Session variables are lost intermittently in ASP.NET applications
http://support.microsoft.com/default.aspx?scid=kb;en-us;Q316148
在1.0的时候也有一个bug会导致工作进程被回收并重启,该bug已经在1.1和sp2中修复。
关于该bug的详细信息请参考:
ASP.NET Worker Process (Aspnet_wp.exe) Is Recycled Unexpectedly.
http://support.microsoft.com/default.aspx?scid=kb;en-us;Q321792
问:什么类型的对象可以保存在Session里?
答:这依赖使用的Session的模式,当使用的是进程内(InProc)的Session那么可以轻松的保存任何对象。如果你使用了非InProc的模式,则只能保存可以序列化和反序列化的对象,如果此时保存的对象不支持序列化,则不能保存到这种模式(非InProc)的Session里。
问:为什么在Session_End中不能使用Response.Redirect和Server.Transfer方法跳转页面?
答:Session_End是一个在服务器内部激发的事件处理函数。它是基于一个服务器内部的计时器的,在激发该事件时服务器上并没有相关的HttpRequest对象,因此此时并不能使用Response.Redirect和Server.Transfer方法。
问:在Session_End中是否可以获得HttpContext对象?
答:不行,因为这个事件并没有和任何的请求(Request)相关联,没有基于请求的上下文。
问:在Web Service中该如何使用Session?
答:为了在Web Service中使用Session,需要在Web Service的调用方做一些额外的工作,必须保存和存储调用Web Service时使用的Cookie。详细信息请参考MSDN文档的HttpWebClientProtocol.CookieContainer属性。然而,如果你使用代理服务器访问Web Service由于框架的限制,两者不能共享Session。
问:当我使用webfarm时,当我重定向到其他的Web服务器时Session为什么会丢失?
答:详细信息请参考:
PRB: Session State Is Lost in Web Farm If You Use SqlServer or StateServer Session Mode
http://support.microsoft.com/default.aspx?scid=kb;en-us;325056
问:Session在global.asax中的那些事件中有效?
答:Session只有在AcquireRequestState事件之后有效,该事件之后的事件都可以使用Session。
问:为了可以顺序访问Session的状态值,Session是否提供了锁定机制?
答:Session实现了Reader/Writer的锁机制:
当页面对Session具有可写功能(即页面有 <%@ Page EnableSessionState="True" %>标记),此时直到请求完成该页面的Session持有一个写锁定。
当页面对Session具有只读功能(即页面有 <%@ Page EnableSessionState="ReadOnly" %>标记),此时知道请求完成该页面的Session持有一个读锁定。
读锁定将阻塞一个写锁定;读锁定不会阻塞读锁定;写锁定将阻塞所有的读写锁定。这就是为什么两个框架中的同一个页面都去写同一个Session时,其中一个要等待另一个(稍快的那个)完成后,才开始写。
问:Session平滑超时意味着什么?
答:Session平滑超时意味着只要你的页面访问(使用)了Session,超时时间将被刷新(可以理解为重新计时),即从该页面请求开始,将重新计算超时时间。但是,该页面不能禁用Session。它会自动的访问当前页面的Session,刷新超时时间。
问:在global.asax中的事件处理函数中Session为什么无效?
答:依赖于在哪个事件处理函数中使用Session,Session在AcquireRequestState事件之后才有效,该事件之后的所有事件处理函数都可以使用Session,之前的则不能。
问:当我使用InProc模式保存Session时,此时的Session是保存在哪里?
答:不同的IIS的处理方式不同,
当使用的是IIS5的时候Session是保存在aspnet_wp.exe的进程空间里的。
当使用的是IIS6时,默认情况下所有的应用程序共享应用程序池,Session保存在w3wp.exe的进程空间中。
问:当页面出现错误后我的Session是否将被保存?我需要在Session_End中处理一些清理工作,但是失败了,为什么?
答:Session_End只有在Session运行在InProc模式下才会被执行。Session_End使用的帐号是运行aspnet_wp工作进程的帐号(这个可以在machine.config中设置)。因此,如果在Session_End方法里,使用集成安全性链接到SQL,它将使用aspnet_wp进程的帐号打开链接,此时成功与否则依赖于你的SQL的安全性设置。
问:在Session_End是我是否可以获得有效的HttpSessionState和HttpContext对象?
答:你可以在这个方法中获得HttpSessionState对象,可以直接使用Session来访问即可。但是不能获得HttpContext对象,因为该事件并没有和任何请求相关联,因此不存在上下文对象。
问:在SQLServer模式下使用Session,为什么我的Session不过期?
答:在SqlServer模式下,Session的过期是通过SQL Agent的注册工作完成的,请检查你的SQL Agent是否运行?
问:当我设置EnableSessionState为“ReadOnly”后,但是我在InProc模式下依然可以修改Session的值,这是为什么?
答:即使EnableSessionState标示为ReadOnly,但是在InProc模式下用户依然可以编辑Session。唯一不同的是,在请求过程中Session将不会被锁住。
问:为什么在切换成SQLServer模式后我的请求被挂起了?
答:检查在Session里面是否都保存的是可以保存在SQLServer模式下的对象,即这些对象必须支持序列化。
问:当Session设置成cookieless后会有什么影响?
答:当把cookieless设置成true时,主要会有下面的约束:
1、在页面中不能使用绝对链接
2、在应用程序中在除了Http和Https之间的切换时需要完成一些其他的步骤。
如果发送一个链接给其他人,此时的URL里面将包含Session ID的信息,所以两个人将公用一个Session。
注:
*p5:Session丢失 http://topic.csdn.net/u/20081208/14/c154543c-8e86-406b-82a2-d3cc6f736b0d.html
5、客户端使用Cookieless的方式存储Session信息
sessionState中的cookieless="false"改为:cookieless="true",这样,客户端的Session信息就不再使用Cookie存储了,而是将其通过URL存储。关闭当前的IE,打开一个新IE,重新访问刚才的Web应用程序,浏览器地址就会变为 http://localhost/MyTestApplication/(
ulqsek45heu3ic2a5zgdl245)/default.aspx中黑体标出的就是客户端的Session ID。注意,这段信息是由IIS自动加上的,不会影响以前正常的连接。 *p6
问:当Session设置成cookieless后会有什么影响?
答:当把cookieless设置成true时,主要会有下面的约束:
1、在页面中不能使用绝对链接
2、在应用程序中在除了Http和Https之间的切换时需要完成一些其他的步骤。
如果发送一个链接给其他人,此时的URL里面将包含Session ID的信息,所以两个人将公用一个Session。 *p7
注:
*p6:[ASP.NET] Session 详解
http://www.blueidea.com/tech/program/2004/1856.asp
*p7:Session丢失
http://topic.csdn.net/u/20081208/14/c154543c-8e86-406b-82a2-d3cc6f736b0d.html
6、Session.SessionID 固定
- IsNewSession:取得值,指出工作階段是否以目前要求建立。
- SessionID:取得工作階段的唯一工作階段識別項。
re: 因為Session在還沒裝物件之前, ID都不是固定的. 如果您賦予Session內容, ex: Session["xxx"]=123 , 您會發現ID就會固定. *p8
注:
*p8:[ASP.Net]Session.IsNewSession與Session.SessionID http://www.dotblogs.com.tw/yilinliu/archive/2009/04/24/8163.aspx
posted on 2010-05-10 10:34
黄小二 阅读(626)
评论(0) 编辑 收藏 所属分类:
ASP.NET