Session 详解
Session 详解
引子
想一个问题, 有一个商店要做一个活动,对于在本店累计消费超过2000元的客户 ,可以领取小礼品一份。要如何实现 。
- 每次消费给客户一张消费凭证如发票等 ,用户兑奖把这些发票都带过来 。
- 给客户办一张会员卡,客户结账时出示会员卡,收银员可以在商店的管理系统查到客户的历史消费记录 ,然后兑奖。
是什么
字面意思 会话(对话) ,会话机制 ,客户端发起对话,服务端回答,经过多次对话后,让服务端拥有知道之前和某个客户聊了什么的机制 。
其他
- session 是一种服务端机制 ;
- 因为http协议无状态,所有需要状态管理 ( 记得上一讲 ,为什么有cookie 也是这个原因么 );
- 不同web平台都有对session机制的实现;
建立会话:
客户端请求服务端,服务端检测这边有没有存储和这个客户的对话。如果没有就建立会话 ,有的话继续维护当前会话。(思考问题,通过什么检测有没有和这个客户的对话)
断开会话:
服务端销毁某个会话数据,会使其断开;客户端长时间不访问服务端,根据配置的session过期时间,服务端会销毁和某个客户端会话数据。
同时,客户端也可以断开会话,只需要客户端不告诉服务端sessionid,或者换一个开启一段新的会话。
分清楚一个概念:会话状态和登录状态的区别
会话状态虽然常常被用来标识登录状态。但是却不能完全等同 ;登录状态很好理解,用户没有登录之前,是未登录状态。 输入账号密码(或其他方式)登录验证成功之后是 已登录状态。
那什么时候开始有会话状态的呢 ?
举一个例子来证明没有登录,会话状态已经产生了 :比如登录或者注册时的图形验证码 。
不同web平台中对session的实现
不同web开发框架都有对session机制的 实现,或者叫封装 ,常见的平台如下图:
平台 | 核心对象 | 默认存放sessionId的cookie name | 使用语法 |
c# | System.Web.SessionState.HttpSessionState | ASP.NET_SessionId | Session[""]=3; |
php | $_SESSION | PHPSESSID | $_SESSION['33']=1; |
java | javax.servlet.http.HttpSession | JSESSIONID | HttpSession session = request.getSession(); session.setAttribute("data", "sfe"); |
… | … | … | … |
Asp.net 对Session的实现
我们从Session在web.config文件中的配置讲起:参考
- session在web.config中的配置
挑几个关键属性讲下:
- mode
- Off: 关闭,不使用cookie
- InPro: 当前进程,也就是w3wp进程
- SQLServer :会话状态正在使用进程外 SQL Server 数据库存储状态信息。Aspnet_regsql.exe 工具
- StateServer:会话状态将使用进程外 ASP.NET 状态服务来存储状态信息, windows服务aspnet_state.exe
- Custom : 自定义,自己实现SessionStateStoreProviderBase这个抽象类就可以了,然后配置:
- cookieless
- AutoDetect :session机制根据浏览器对cookie的支持情况决定是使用cookie还是url传递sessionid
- UseCookies :显式指定使用cookie 传递sessionid【推荐】
- UseDeviceProfile :session机制根据浏览器对cookie的支持情况决定是使用cookie还是url传递sessionid
- UseUri: 显式指定用url传递sessionid
常见Session丢失原因
1、Session超时,用户打开页面,页面长时间不操作会导致此原因
2、IIS应用程序池回收,或者重启
3、Web.Config修改,即IIS应用程序池重启
4、dll被替换或者动态页面修改,即IIS应用程序池重启
5、杀毒软件对.config文件进行扫描,可能会导致IIS应用程序池回收
6、用户浏览器禁用cookie
7、其他原因
asp.net Session 进阶
Session 共享
两个网站会话共享, a网站登录,b网站也登录了,根据session的原理 ,session是通过客户端的cookie里的sessionid 来识别同一个用户发来的请求,所以这里这里就是要连个网站sessionid一样 ,也就是cookie相同,但是cookie是不能跨域传输的,但是只要主域一样 ,将cookie的域设置成domain.com
,cookie会发送到这个主域下所有子域对应的网站。
是否发送到两个网站服务端的sessionid一样,session就共享了呢,其实不然 ,
如果session mode 是Inpro 模式,这明显不行,因为session存在各自的网站进程里面,
如果session mode是 stateServer模式呢 ,其实也不行,需要进行一些小修改就好,因为session的存储结构不单单是 sessionid 和session里面的内容 ,他是sessionid 和网站唯一标志共同来唯一指定的,我们可以通过一些手段骗session机制,两个不同的网站的唯一标志是一样的。
session mode 是sqlserver 和上面的方案差不多,也是要进行些修改,让网站标志一样 。
可以看到实现session的共享还是很麻烦的。
- 设置存储sessionid的cookie的域是主域
- 将session存在 stateserver 或者sqlserver (性能会有所影响) ,
- 骗asp.net session机制,不同网站的网站唯一标志是一样的。
网站负载了 Session 还可用么
这个问题还需要有负载均衡相关知识才能了解,简而言之,同样的web程序部署多个,客户端发出的请求根据算法分配到其中某一个服务端处理。
首先可以确定,发送到多个程序的sessionid是一样的,接着就是服务端能根据sessionid获取到同样的会话数据吗?
这个问题和上面很像 ,是不能的,因为网站的标志不一样的。说解决方案也和上面差不多了,少了第一步。
Session 的并发缺点
微软官方的几种sessionmode provider 都有这个问题,在一段会话里面 ,服务端会按照循序处理客户端发过来的会话请求 ,也就是说,上一个请求没处理完,浏览器就发起了下一个请求的话会被挂起,直到上一个会话请求处理完成。这种并发情况可能常见于一个页面上对服务端发出多个异步请求,如果某个请求处理时间很长 ,后面就请求就会被挂起。虽然.net 提供了关闭某个地址session的配置,但是通常业务场景中都是需要会话状态的。
不用Asp.net Session 用什么
我们把这个问题转换一下,因为
常见的session使用场景是
- 存储验证码
- 存储用户基础信息,如id ,姓名,角色等
- 作为身份验证,登录验证
- 多个页面间传值
- ???
那么就是找到处理这些场景问题解决方案就可以了 。
能不能把用cookie加密存储。 或者cache +cookie ,redis +cookie ,
另外身份验证可以用。net自带 forms 身份验证。
Q&A
- 为什么session(如果作为登录状态,那就会造成重新登录)莫名其妙丢失 ?
- 向session里面写数据时报错 ,无法序列化
无法序列化会话状态。在“StateServer”或“SQLServer”模式下,ASP.NET 将序列化会话状态对象,因此不允许使用无法序列化的对象或 MarshalByRef 对象。如果自定义会话状态存储在“Custom”模式下执行了类似的序列化,则适用同样的限制。
- 用来承载会话的cookie ,有什么特征。
- 如果让你实现一个简单的session机制需要做哪些事 。
转载请遵循此协议:署名 - 非商业用途 - 保持一致
并保留此链接:http://fejerry.cnblogs.com/