一.关于Session,SessionID和Cookiesweb
Session数据保存在服务器端, 可是每个客户端都须要保存一个SessionID, SessionID保存在Cookies中, 关闭浏览器时过时.数据库
在向服务器发送的HTTP请求中会包含SessionID, 服务器端根据SessionID获取获取此用户的Session信息.c#
不少初级开发人员不知道SessionID和Cookies的关系, 因此经常认为二者没有联系. 这是不正确的. 正是由于SessionID保存在Cookies中, 因此在咱们保存Cookies的时候,必定要注意不要由于Cookies的大小和个数问题而致使SessionID对象. 在咱们的程序中, 对SessionID的Cookies有特殊的处理:浏览器
/// <summary> /// 写入cookie. /// </summary> /// <param name="day"></param> /// <returns></returns> public bool SetCookie(int day) { string CookieName = GetType().ToString(); HttpCookie SessionCookie = null; //对 SessionId 进行备份. if (HttpContext.Current.Request.Cookies["ASP.NET_SessionId"] != null) { string SesssionId = HttpContext.Current.Request.Cookies["ASP.NET_SessionId"].Value.ToString(); SessionCookie = new HttpCookie("ASP.NET_SessionId"); SessionCookie.Value = SesssionId; } //省略掉中间的代码部分.只保留备份SessionID和找回SessionID的逻辑 //若是cookie总数超过20 个, 重写ASP.NET_SessionId, 以防Session 丢失. if (HttpContext.Current.Request.Cookies.Count > 20 && SessionCookie != null) { if (SessionCookie.Value != string.Empty) { HttpContext.Current.Response.Cookies.Remove("ASP.NET_SessionId"); HttpContext.Current.Response.Cookies.Add(SessionCookie); } } return true; }
二.搭建Session服务器的几种方式安全
将Session保存在独立的服务器中能够实如今多台Web服务器之间共享Session.虽然咱们也能够本身开发Session存储系统, 可是使用ASP.NET自带的存储机制将更加便捷.
服务器
方式名称 存储方式cookie
1.Off 设置为不使用Session功能session
2.InProc 设置为将Session存储在进程内,就是ASP中的存储方式,这是默认值。并发
3.StateServer 设置为将Session存储在独立的状态服务中。一般是aspnet_state.exe进程.负载均衡
4.SQLServer 设置将Session存储在SQL Server中。
5.Customer 自定制的存储方案
三.使用 StateServer 模式搭建Session服务器
1.启动 Asp.net State service服务.(这个服务默认的状态为手动.修改成自动并启动.)
2.修改注册表: [HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\aspnet_state\Parameters]
设置 AllowRemoteConnection = 1 , 设置 Port = 42424 (十进制,默认即为42424)
Port是服务的端口号
AllowRemoteConnection 表示是否容许其余机器链接,0为仅能本机使用,1为能够供其余机器使用.
在Web应用程序的Web.Config中, 咱们须要修改 <configuration> / <system.web> 的<sessionState>节点.若是没有
没有则添加(默认使用的是InProc方式)
<sessionState mode="StateServer" stateConnectionString="tcpip=服务器ip:42424" cookieless="false" timeout="60"/>
上面的参数咱们能够根据须要修改.
四.使用经验与技巧总结
下面是SessionID, Session_End时间, StatServer模式 和 SqlServer模式的各类经验和技巧总结.
1.在web farm中,请确认在全部的web服务器上有相同的<machineKey>
2. 要保存在Session中的对象是可序列化的。
3.为了在web farm中的不一样web服务器上维护session state,IIS Metabase中的网站应用程序路径(如\LM\W3SVC\2)应该在全部的服务器上保持一致(大小写敏感).
4. ASP.NET处理Session是在Machine.Config中配置的HttpModuel模块, 在.NET的安装目录下的Config文件夹中, 查看Web.Config(1.1版本是在Machine.Config):
<httpModules> ...
<add name="Session" type="System.Web.SessionState.SessionStateModule"/> ...
</httpModules>
确认此模块是否存在.
5.StateServer不支持负载均衡, 因此若是大并发推荐使用SqlServer模式, 能够享受到SqlServer的高性能和安全性.虽然存储效率会有降低.
6.须要让全部机器的MachineKey相同.在Machine.Config中配置:
<machineKey validationKey="1234567890123456789012345678901234567890AAAAAAAAAA" decryptionKey="123456789012345678901234567890123456789012345678" validation="SHA1" decryption="Auto" />
1. 要保存在Session中的对象是可序列化的。
2. 若是使用了默认是数据库, 则在客户端配置文件中的数据库连接字符串的用户,须要拥有ASPState和tempdb两个库的dbowner权限.
3. 在SQLServer模式下,session过时是由SQL Agent使用一个注册任务完成的,要确认SQL Agent已经运行。不然没法清理过时的Session数据, 会致使数据库数据一直增长.
4. 若是使用SqlServer模式时, 对于Web场中的各服务器的 ASP.NET 应用程序路径必须是相同的。请在 IIS 配置数据库中对 Web 场中的全部 Web 服务器进行 Web 站点的应用程序路径同步。大小写必定要相同,由于 Web 站点的应用程序路径是区分大小写的。
5.须要让全部机器的MachineKey相同.在Machine.Config中配置:
<machineKey validationKey="1234567890123456789012345678901234567890AAAAAAAAAA" decryptionKey="123456789012345678901234567890123456789012345678" validation="SHA1" decryption="Auto" />
1. 不能直接经过Session服务器在ASP.NET和ASP之间共享Session. 请使用微软提供的解决方案:
http://msdn.microsoft.com/zh-cn/library/aa479313.aspx
2. 在不一样的应用程序或一个网站的不一样虚拟目录之间没法共享Session
3. Session的过时时间是滑动时间.
4. Session存储.NET自带的值类型性能最优. 存储对象会下降性能.
1.SessionID 还能够保存在URL上, 设置Web.Config文件中的System.Web/sessionState节点的Cookiesless属性便可:
<sessionState cookieless="UseUri" />
2. 通常在Session超时或删除以后,SessionID保持不变. 由于Session过时后会在服务器端清除数据, 可是SessionID保存在用户浏览器上, 因此只要浏览器不关闭则HTTP头中的SessionID保持不变.
3.关闭浏览器后再访问, SessionID会不一样.
4.每打开一个IE6窗口, SessionID都不一样, 在IE6中两个窗口的Session不能共享.
5.FireFox的标签页和新的FireFox窗口, SessionID都相同, 在FF的窗口和标签页上Session能共享.
6.对于包含FrameSet的页面,好比:
<frameset cols="25%,50%,25%"> <frame src="SessionID.aspx"> <frame src="SessionID.aspx"> <frame src="SessionID.aspx"></frameset>
若是后缀名是.htm而且.htm文件没有交给ASP.NET的ISAPI处理, 那么根据服务器速度在每一个Frame页面生成不一样的SessionID, 再刷新后相同都等于最后一个SessionID.
解决办法是将.htm后缀改为.aspx, 或者将.htm文件交给ASP.NET的ISAPI处理.
1. Session_End仅在InProc模式中可用
2. 关闭浏览器,Session_End是不会触发的。HTTP是一种无状态协议,服务器没有办法知道你的浏览器是否已经关闭。
3. 当Session由于时间过时或调用Session.Abandon时,Session_End才会触发.Session.Clear()仅仅是清除数据,但没有删除session。
4. Session_End由一个后台线程触发,使用工做者进程帐号运行. 因此程序不会通知发生的错误.
5. 在Session_End访问数据库要考虑权限问题. Session_End是用运行工做者进程(aspnet_wp.exe)的账号运行的,这个帐号能够在machine.config中指定。所以,在Session_End中,若是使用integrity security链接SQL,它将使用工做者进程帐号身份链接,这可能会引发登陆失败.
6.由于Session_End是有独立线程出发的, 因此在Session_End中没法使用HttpContext对象(Request,Response,Server等对象都在HttpContext中), 即没法使用 Response.Redirect 和Server.Transfer等方法.