Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2306788
  • 博文数量: 266
  • 博客积分: 5485
  • 博客等级: 大校
  • 技术积分: 3695
  • 用 户 组: 普通用户
  • 注册时间: 2007-06-20 11:05
个人简介

多读书,多做事,广交朋友,趣味丛生

文章分类

全部博文(266)

分类: C/C++

2010-01-21 10:19:26

Session又称为会话状态,是Web系统中最常用的状态,用于维护和当前浏览器实例相关的一些信息。举个例子来说,我们可以把已登录用户的用户名放在Session中,这样就能通过判断Session中的某个Key来判断用户是否登录,如果登录的话用户名又是多少。
Session对于每一个客户端(或者说浏览器实例)是“人手一份”,用户首次与Web服务器建立连接的时候,服务器会给用户分发一个SessionID作为标识。SessionID是一个由24个字符组成的随机字符串。用户每次提交页面,浏览器都会把这个SessionID包含在HTTP头中提交给Web服务器,这样Web服务器就能区分当前请求页面的是哪一个客户端。那么,ASP.NET 2.0提供了哪些存储SessionID的模式呢:
·      Cookie(默认)。如果客户端禁止了Cookie的使用,Session也将失效。
·      URL。Cookie是否开启不影响Session使用,缺点是不能再使用绝对链接了。
ASP.NET 2.0对于Session内容的存储也提供了多种模式。
·      InProc(默认)。Session存储在IIS进程中(Web服务器内存)。
·      StateServer。Session存储在独立的Windows服务进程中(可以不是Web服务器)。
·      SqlServer。Session存储在SqlServer数据库的表中(SqlServer服务器)。
虽然InProc模式的Session直接存储在Web服务器IIS进程中,速度比较快,但是每次重新启动IIS都会导致Session丢失。利用后两种模式,我们就完全可以把Session从Web服务器中独立出来,从而减轻Web服务器的压力,同时减少Session丢失的概率。
因此,SessionID存储在客户端(可以是Cookie或者URL),其他都存储在服务端(可以是IIS进程、独立的Windows服务进程或者SQL Server数据库中)。
要把Session存储在Windows服务进程中需要进行以下几个步骤。
第1步是打开状态服务。依次打开“控制面板”→“管理工具”→“服务”命令,找到ASP.NET状态服务一项,右键单击服务选择启动。如果你正式决定使用状态服务存储Session前,别忘记修改服务为自启动(在操作系统重启后服务能自己启动)以免忘记启动服务而造成网站Session不能使用。
第2步,在system.web节点中加入:
stateNetworkTimeout="20">
注意:只有把对象标注为可序列化后才能在服务中进行存储。什么是序列化呢?序列化是指将对象实例的状态存储到存储媒体的过程。在此过程中,先将对象的公共字段和私有字段以及类的名称转换为字节流,然后再把字节流写入数据流。在随后对对象进行反序列化时,将创建出与原对象完全相同的副本。要使一个类可序列化,最简单的方法是使用 Serializable 属性对它进行标记。
[Serializable]
class MyUser
{
    public string sUserName;
    public int iAage;
    public override string ToString()
    {
        return string.Format("姓名:{0},年龄:{1}", sUserName, iAage);
    }
}
把Session存储在数据库中
1.在命令行窗口输入cmd并在命令行中运行如下命令。
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regsql.exe -S .\SqlExpress -E –ssadd
其中C:\Windows用你自己Windows的目录代替,v2.0.50727用你安装的2.0框架的版本号代替。-S指定SqlServer服务器地址,-E表示采用信任连接,-ssadd表示为SqlServer服务器添加状态服务的支持。操作结束后,你可以使用IDE的服务器资源管理器连接SqlExpress数据库,可以看到多了一个ASPState数据库,但是奇怪的是数据库中没有任何表却有很多存储过程,其实,所有Session的数据都存放在了tempdb数据库内。
其实,aspnet_regsql.exe有一个-sstype参数可以用来指定Session的内容和操作的存储过程存放的表。由于篇幅关系,在这里就不详细介绍了,读者可以使用aspnet_regsql.exe/?来浏览程序详细的使用方式。
2.打开Web.config文件,修改前面建立的sessionState节点。
 
因此Session能存储的类型为: 对于InProc模式是一切类型,而对于StateServer和SqlServer模式是一切可以序列化的类型。
不要滥用session,建议在session中存储小于100k的数据。
默认情况下,Session的超时时间(Timeout)是20分钟,用户保持连续20分钟不访问网站,则Session被收回,如果在这20分钟内用户又访问了一次页面,那么20分钟就重新计时了,也就是说,这个超时是连续不访问的超时时间,而不是第一次访问后20分钟必过时。这个超时时间同样也可以通过调整Web.config文件进行修改:
当然你也可以在程序中进行设置:
Session.Timeout = "30";
一旦Session超时,Session中的数据将被回收,如果再使用Session系统,将给你分配一个新的SessionID。
以下情况可能会引起session丢失:
·      bin目录中的文件被改写。asp.net有一种机制,为了保证dll重新编译之后,系统正常运行,它会重新启动一次网站进程,这时就会导致Session丢失,所以如果有access数据库位于bin目录,或者有其他文件被系统改写,就会导致Session丢失。
·      SessionID丢失或者无效。如果你在URL中存储SessionID,但是使用了绝对地址重定向网站导致URL中的SessionID丢失,那么原来的Session将失效。如果你在Cookie中存储SessionID,那么客户端禁用Cookie或者Cookie达到了IE中Cookie数量的限制(每个域20个),那么Session将无效。
·      如果使用InProc的Session,那么IIS重启将会丢失Session。同理,如果使用StateServer的Session,服务器重新启动Session也会丢失。
一般来说,如果在IIS中存储Session而且Session的Timeout设置得比较长,再加上Session中存储大量的数据,非常容易发生Session丢失的问题。
最后,Session的安全性怎么样呢?我们知道,Session中只有SessionID是存储在客户端的,并且在页面每次提交的过程中加入HTTP头发送给服务器。SessionID只是一个识别符,没有任何内容,真正的内容是存储在服务器上的。总的来说安全性还是可以的,不过笔者建议你不要使用cookieless和SqlServer模式的Session。把SessionID暴露在URL中,把内容存储在数据库中可能会发生攻击隐患。
·      如何遍历当前的Session集合。
System.Collections.IEnumerator SessionEnum = Session.Keys.GetEnumerator();
while (SessionEnum.MoveNext())
{
    Response.Write(Session[SessionEnum.Current.ToString()].ToString() + "
");
}
如何立刻让Session失效。比如用户退出系统后,Session中保存的所有数据全部失效,可以使用以下代码来让Session失效。
Session.Abandon();
 
Session的常见问题与总结
Session的基本知识就介绍到这里,现在再回头看第一节中的几个问题,你是否都能回答了呢?为了强化大家的概念,笔者就三种模式的Session进行了一个比较(假设都使用Cookie来存储SessionID)。
表12.1  三种模式的Session比较
  

 
在使用Session的过程中你可能还会遇到很多奇怪的问题,结束本节之前笔者列出了几条常见的FAQ,供大家参考:
·      为什么每次请求的SessionID都不相同?
n  可能是没有在Session里面保存任何信息引起的,即程序中任何地方都没有使用Session。只有在Session中保存了内容后,Session才会和浏览器进行关联,此时的SessionID将不会再变化。
·      为什么当我设置cookieless为true后,在重定向的时候会丢失Session?
n  当使用cookieless时,你必须使用相对路径替换程序中的绝对路径,如果使用绝对路径,ASP.NET将无法在URL中保存SessionID。
·      有办法知道应用程序的Session在运行时占用了多少内存吗?
n  没有办法,你可以通过观察IIS进程(InProc模式)或者aspnet_state进程(StateServer模式)大致估计。
·      有没有可能知道整个网站使用Session的用户列表?
n  对于InProc模式和StateServer模式很难,对于SqlServer模式你可以查询存储Session的表进行尝试。
·      当页面中设了frameset,发现在每个frame中显示页面的SessionID在第一次请求时都不相同,为什么?
n  原因是你的frameset是放在一个HTML页面上而不是ASPX页面。在一般情况下,如果frameset是aspx页面,当你请求页面时,它首先将请求发送到Web服务器,此时已经获得了SessionID,接着浏览器会分别请求Frame中的其他页面,这样所有页面的SessionID就是一样的,就是FrameSet页面的SessionID。然而如果你使用HTML页面做FrameSet页面,第一个请求将是HTML页面,当该页面从服务器上返回时并没有任何Session产生,接着浏览器会请求Frame里面的页面,这样,这些页面都会产生自己的SessionID,所以在这种情况下就可能出现这种问题。当你重新刷新页面时,SessionID就会一样,并且是最后一个请求页面的SessionID。
 
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/popotans/archive/2009/11/14/4810842.aspx
阅读(3019) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~