Session 存储方式
这个唯一的SessionId还是有很大的实际意义,当一个用户提交表单时,浏览器就会将用户的SessionId自动附加在HTTP头信息中,当服务器 处理完这个表单后,就会将结果返回给SessionId所对应的用户。
如下是Web.config如何配置Session的:
<configuration>
<system.web>
<sessionState mode=" Off | InProc | StateServer | SQLServer "
cookieless=" true | false "
timeout=" number of minutes "
stateConnectionString=" tcpip=server:port "
sqlConnectionString=" sql connection string "
stateNetworkTimeout=" number of seconds " />
</system.web>
</configuration>
其中各个节点属性:
mode: Session的存储方式(必有的属性)。
InProc:将Session存到进程内(这是Default值。)
off:禁用Session.
StateServer:将Session存到独立的状态服务中(Asp.net State Service).
SqlServer:将Session存到SqlServer中。
Cookieless:设置客户端Session存储的方式。
false:使用Cookie模式(default).
true:使用Cookieless模式。
timeout:设置Session过期时间(default is 20 minutes)
stateConnectionString: 设置Session独立存放的状态服务所在服务器的名称(地址)和端口号,当mode=“stateserver时,这个属性就是必 须的。
sqlConnectionString:设置与Sqlserver的连接字符串,当mode="sqlserver"时,这个属性时必须的。
stateNetWorkTimeout:设置当mode=“StateServer”时,经过多少秒空闲后, 断开web服务器与存储状态信息服务器的TCP/IP连接(default is 10 seconds).
asp.net中客户端Session的存储。
asp.net中,默认是使用Cookie存储Session的,如果是将cookieless="false",改成 cookieless="true",则session就不用cookie来存储了,而是使用url来存储。
asp.net服务器端session存储在进程内(inproc)
当mode="Inproc"时,服务器的Session存储在IIS进程中,当IIS关闭,重启时,这些Session信息就会丢失,但这种模式最大的 好处就是性能提高。
asp.net服务器端Session存储在进程外(StateServer)
当mode="StateServer"时,服务器的Session就存储在"ASP.NET State Server"这个服务的进程中,在服务中找到名为:“ASP.NET State Service”的服务,启动这个服务,在资源管理器的进程中就能找到一个名 为:“aspnet_state.exe"的进程,这个就是我们保存 Session的进程。
”ASP.NET State Server"服务可以与Web服务器分开.eg:web服务器在192.168.0.100上,“asp.net state service"服务在192.168.0.101上,则可以进行设置:
mode="StateServer" stateConnection="tcpip=192.168.1.101:42424".
asp.net服务器端Session存储到SQLServer中(SQLServer),
当mode="sqlserver"时,服务器的Session就是存储到Sql server中建立一个存储Session的数据库。在
%windir%\Microsoft.NET\Framework\v2.0.50727 下有个名为: InstallSqlState.sql 的sql脚本文件. 这个脚本是专门用来建存储Session的数据库以及一个维护Session信息数据库的SQL Server代理作业的.
执行此sql脚本后,会看到一个新增的aspstate数据库,但这个数据库中,只有存储过程,没有用户表,用户表放到了tempdb这个数据库中去 了,ASpstateTempSessions和ASPStateTempApplications,Session信息存储到了 ASPStateTempApplication存储了asp中Application对象信息。
另外查看管理->SQL Server代理->作业,会发现多了一个名为:
ASPState_job_DeleteExpiredSession的作业,这个作业实际上是每分钟去ASPStateTempSession中 删除过期的Session信息。
上面的方法是建立Session数据库的一个”官方“方法,但在实际的应用中一般没这么去建,而是采用另一种方法,使用下面这段命令来自动创建 Session数据库:
aspnet_regsql.exe -S ServerName\InstanceName -U User -P Password -d DBName -ssadd -sstype c
此命令将在ServerName\InstanceName建立DBName的数据库, 用户存储Session的数据库. 此数据库中包含了存储过程和用户表. 同时在SQL Server代理 -> 作业 中也加入了相应的作业.
然后在Web.config中设置好配置信息:
mode="SQLServer" sqlConnectionString="data source=ServerName\InstanceName; Integrated Security=SSPI;"
"Integrated Security=SSPI;" 是指使用Windows集成身份验证.
如果使用SQL用户登陆方式. 则在sqlConnectionString中设置好"userid=sa; password=***".
这样一来就可以将Session存放到SQLServer中了
不得不说当我了解了session的原理之后感觉到了惊讶,因为session竟然是基于cookie的,所以当一向被认为不安全的cookie和超安全的session等同之后确实很让人接受不了,因为我确实是菜鸟
做了这么多年的web,用了这么多年的session和cookie,竟然就习惯了这两个东西,把他们的功能当成了天然的功能,从来没有考虑过他们的原理,实在是悲哀,直到有一天,我觉醒了。。
首先应该了解http协议的请求过程,这个以前倒是知道,当然是基于tcp/ip协议,客户端请求服务器,服务器回答客户端,无状态的,那么服务器如何区分客户端的呢?看完本文自然明白了
关于cookie
先来说cookie,怎么使用就不说了,cookie按照在客户端存放的方式,可以分为两类,
一种是会话性质的cookie,存放在浏览器内存中,当你在用代码向客户端写入cookie的时候,如果没有指定过期时间,那么cookie是存放在浏览器的内存里面的,不会持久化在硬盘上,也就是你在浏览器的临时文件里找不到!
一种是持久化的cookie,存放在硬盘上,当你指定了cookie的过期时间,那么,在客户端写入cookie的时候就会在浏览器的临时文件下生成一个文件,具体格式和名字可以到浏览器临时文件去看下
cookie的原理是这样的:当你在服务器端的代码里写了response.cookie["mycookie"]="mytestcookie"的时候,返回给客户端的http响应中,会在http相应头中加入cookie的信息,浏览器收到相应后,会按照http响应头里的cookie在客户端建立cookie。
客户端的cookie也是插在http头中发送到服务器端的,并且,一个域,在客户端建立的所有cookie,在客户端的每一次的http请求都会带着,比如testwebsite.com这个站点,任何时刻写到客户端的cookie,只要不过期,浏览器在向testwebsite.com发送http请求的时候,会带上这些cookie,所以cookie在客户端的大小是有限制的
关于session
cookie明白了之后session就容易理解了,asp的session和asp.net默认的session就是通过第一种cookie来实现的,你可以把自己的浏览器的cookie彻底禁用,然后再去登录一些注册过的门户网站,会发现很多都登录不了了。是cookie,将http的请求变得有状态。session的实现是web服务器的事情,不过很显然是利用会话cookie,也就是存放在浏览器内存里的那种cookie来实现的,在cookie里只是存放了SessionID,然后在服务器上建立了一张表,对应客户端的SessionID。这张表是存放在服务器上的进程中的,也就是服务器的内存里,也就是Application里。当客户端请求服务器的时候,如果服务器发现这是一个新的请求,就会分配给他一个SessionID,也就是在浏览器写入一个sessionID的cookie。你可以试一下,在你请求过一次服务器之后,在服务器遍历客户端所有的cookie,就会发现这个叫做SessionID的cookie。
所以在了解了这个session的原理之后我们可以自己来造一个自己的session,过程就不说了。
那么我们现在可以说session就是依赖于会话性的cookie的
关于session的其他
asp.net可以定制session的实现方式,默认是上面说的原理,但是可以改变的。
可以选择不依赖于cookie,就是把sessionID作为URL的一部分放在每一次的请求后面,像这样:
http://www.testwebsite.com/(-此处为一串sessionID的字符串-)/test.aspx
但是这种方式你如果在html中指定url的时候,指定了绝对路径,比如
<a href="http://www.testwebsite.com/other.aspx">test</a>
那么点击这个链接就会不是同一个会话了,因为此时区分客户端的唯一标志就是域名后面那串字符串
php也有类似的做法,不依赖cookie的做法是在get的参数里面带一个sessionID的参数
asp.net还可以定义session里存放数据的存储位置,放在其他进程,放在sqlServer中等等,知道了session的原理就很容易明白,我们可以自己就可以造一个类似session作用的东西的
session的结束问题
还有知道了session的原理就会明白一个session会话如何结束,除非服务器端可以清除一个session会话,客户端是没有能力清除session的,关闭浏览器的时候并不能够结束当前的会话(忽略浏览器关闭事件),在不依赖于cookie的session中最明显,你可以记下你的sessionID那串字符串,关闭浏览器,打开,把sessionID自己替换,你就可以恢复刚才的会话了。所谓的20分钟session超时,是服务器每隔20分钟对于不活动的session清除而已。
还有要指出的是依赖于cookie的session是存放在浏览器内存中的,所以一个浏览器的进程就会产生一个session,可以通过任务管理器查看进程,对于IE来说,只有双击桌面上的浏览器快捷方式才能新启动一个进程的,当然其他类似启动iexplorer.exe的行为也可以
到这里你会发现在依赖于cookie的session中,是需要浏览器的支持的!所以当你不用浏览器而自己来制造http请求的时候,session就用了!
对于js的ajax请求,确切的说是xmlhttp这个组件发送的http请求,虽然是你使用js的代码自己制造的,但是依然是借助于浏览器发送的,所以可以获得session。
所以在webservice中使用session我们还得自己造一个东西实现cookie的功能
如果你使用InProc模式的Session,存储过多的数据会导致IIS进程被回收,引发Session不断丢失。
· 如果你使用StateServer存储Session,那么数据在存入Session以前需要进行序列化,序列化会消耗大量的CPU资源。
· 如果你使用SqlServer模式的Session,数据不但要序列化而且还是存储在磁盘上,更不适合存储大量数据。
SessionID是一个由24个字符组成的随机字符串
ookie是否开启不影响Session使用,缺点是不能再使用绝对链接了。
stateNetworkTimeout属性表示从状态服务器请求Session数据最长的时间,默认为10秒,如果网络连接不是很好,请把这个数字适当设置得大一点。
只有把对象标注为可序列化后才能在服务中进行存储。什么是序列化呢?序列化是指将对象实例的状态存储到存储媒体的过程。在此过程中,先将对象的公共字段和私有字段以及类的名称转换为字节流,然后再把字节流写入数据流。在随后对对象进行反序列化时,将创建出与原对象完全相同的副本。要使一个类可序列化,最简单的方法是使用 Serializable 属性对它进行标记。
因此Session能存储的类型为: 对于InProc模式是一切类型,而对于StateServer和SqlServer模式是一切可以序列化的类型。
一定程度上反映了Session是不能跨应用程序的。举例来说,我们在计算机上建立了两个网站,同时都使用Session[“UserName”]来保存登录的用户名,一个网站的用户登录后,另一个网站直接访问Session[“UserName”]是取不到任何值的。那么,Session是否可以跨用户呢?通过前面的分析我们知道,肯定是不行的,Session通过SessionID来区分用户,一般来说SessionID是不可能出现重复的现象,也就是说Session一般是不会“串号”的。既然页面每次提交的时候都会附加上当前用户的SessionID,那么Session应该是可以跨页面的,也就是说一个网站中所有的页面都使用同一份Session。你可以自己来做个试验,请读者打开刚才那个页面,然后按Ctrl+N组合键再打开第二个同样的页面,单击第一个页面中的“写入Session”按钮,单击第二个页面中的“读取Session”按钮,可以发现Session的值被正确读出了。第三个问题的答案有了。
表12.1 三种模式的Session比较
InProc |
StateServer |
SQLServer |
|
存储物理位置 |
IIS进程(内存) |
Windows服务进程(内存) |
SQLServer数据库(磁盘) |
存储类型限制 |
无限制 |
可以序列化的类型 |
可以序列化的类型 |
存储大小限制 |
无限制 |
||
使用范围 |
当前请求上下文,对于每个用户独立 |
||
生命周期 |
第一次访问网站的时候创建Session超时后销毁 |
||
优点 |
性能比较高 |
Session不依赖Web服务器,不容易丢失 |
|
缺点 |
容易丢失 |
序列化与反序列化消耗CPU资源 |
序列化与反序列化消耗CPU资源,从磁盘读取Session比较慢 |
使用原则 |
不要存放大量数据 |
· 为什么当我设置cookieless为true后,在重定向的时候会丢失Session?
n 当使用cookieless时,你必须使用相对路径替换程序中的绝对路径,如果使用绝对路径,ASP.NET将无法在URL中保存SessionID。
为什么每次请求的SessionID都不相同?
n 可能是没有在Session里面保存任何信息引起的,即程序中任何地方都没有使用Session。只有在Session中保存了内容后,Session才会和浏览器进行关联,此时的SessionID将不会再变化
打开iecookiesview,这款软件是拿来察看和修改本机的cookies的,很方便我们的cookies欺骗入侵。
在iecookiesview 里找到你要欺骗的那个网站,看到了吗?有你的用户名和md5加密的密码,我们吧这两项改为管理员的,就是把刚才数据库里面的管理员账号和md5加密的密码代替你自己的。点击“更改cookies”,打开一个新的ie,然后再去访问那个论坛,看到没有?你现在已经是管理员了。
接着,麻烦的事出现了,后台登陆并不是以cookies来实现的,而是以session实现的 ,所以我们同样来欺骗session