zoukankan      html  css  js  c++  java
  • Session 详解

    Session 详解

    引子

    想一个问题, 有一个商店要做一个活动,对于在本店累计消费超过2000元的客户 ,可以领取小礼品一份。要如何实现 。

    1. 每次消费给客户一张消费凭证如发票等 ,用户兑奖把这些发票都带过来 。
    2. 给客户办一张会员卡,客户结账时出示会员卡,收银员可以在商店的管理系统查到客户的历史消费记录 ,然后兑奖。

    是什么

    字面意思 会话(对话) ,会话机制 ,客户端发起对话,服务端回答,经过多次对话后,让服务端拥有知道之前和某个客户聊了什么的机制 。

    其他

    • 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中的配置
    <sessionState
    mode="[Off|InProc|StateServer|SQLServer|Custom]"
    timeout="number of minutes"
    cookieName="session identifier cookie name"
    cookieless=
    "[true|false|AutoDetect|UseCookies|UseUri|UseDeviceProfile]"
    regenerateExpiredSessionId="[True|False]"
    sessionIDManagerType="session manager type"
    sqlConnectionString="sql connection string"
    sqlCommandTimeout="number of seconds"
    allowCustomSqlDatabase="[True|False]"
    useHostingIdentity="[True|False]"
    stateConnectionString="tcpip=server:port"
    stateNetworkTimeout="number of seconds"
    customProvider="custom provider name"
    compressionEnabled="[True|False]"
    sqlConnectionRetryInterval="number of seconds">
    <providers>...</providers>
    </sessionState>

    挑几个关键属性讲下:

    • mode
      • Off: 关闭,不使用cookie
      • InPro: 当前进程,也就是w3wp进程
      • SQLServer :会话状态正在使用进程外 SQL Server 数据库存储状态信息。Aspnet_regsql.exe 工具
      • StateServer:会话状态将使用进程外 ASP.NET 状态服务来存储状态信息, windows服务aspnet_state.exe
      • Custom : 自定义,自己实现SessionStateStoreProviderBase这个抽象类就可以了,然后配置:
    <sessionState mode="Custom" customProvider="MySessionStateStore">
    <providers>
    <clear/>
    <add name="MySessionStateStore" type="Microsoft.Web.Redis.RedisSessionStateProvider" connectionString="RedisConnection"/>
    </providers>
    </sessionState>
    • 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的共享还是很麻烦的。

    1. 设置存储sessionid的cookie的域是主域
    2. 将session存在 stateserver 或者sqlserver (性能会有所影响) ,
    3. 骗asp.net session机制,不同网站的网站唯一标志是一样的。

    网站负载了 Session 还可用么

    这个问题还需要有负载均衡相关知识才能了解,简而言之,同样的web程序部署多个,客户端发出的请求根据算法分配到其中某一个服务端处理。
    首先可以确定,发送到多个程序的sessionid是一样的,接着就是服务端能根据sessionid获取到同样的会话数据吗?
    这个问题和上面很像 ,是不能的,因为网站的标志不一样的。说解决方案也和上面差不多了,少了第一步。

    Session 的并发缺点

    微软官方的几种sessionmode provider 都有这个问题,在一段会话里面 ,服务端会按照循序处理客户端发过来的会话请求 ,也就是说,上一个请求没处理完,浏览器就发起了下一个请求的话会被挂起,直到上一个会话请求处理完成。这种并发情况可能常见于一个页面上对服务端发出多个异步请求,如果某个请求处理时间很长 ,后面就请求就会被挂起。虽然.net 提供了关闭某个地址session的配置,但是通常业务场景中都是需要会话状态的。

    不用Asp.net Session 用什么

    我们把这个问题转换一下,因为

    常见的session使用场景是

    1. 存储验证码
    2. 存储用户基础信息,如id ,姓名,角色等
    3. 作为身份验证,登录验证
    4. 多个页面间传值
    5. ???

    那么就是找到处理这些场景问题解决方案就可以了 。
    能不能把用cookie加密存储。 或者cache +cookie ,redis +cookie ,
    另外身份验证可以用。net自带 forms 身份验证。

    Q&A

    1. 为什么session(如果作为登录状态,那就会造成重新登录)莫名其妙丢失 ?
    2. 向session里面写数据时报错 ,无法序列化
      无法序列化会话状态。在“StateServer”或“SQLServer”模式下,ASP.NET 将序列化会话状态对象,因此不允许使用无法序列化的对象或 MarshalByRef 对象。如果自定义会话状态存储在“Custom”模式下执行了类似的序列化,则适用同样的限制。
    3. 用来承载会话的cookie ,有什么特征。
    4. 如果让你实现一个简单的session机制需要做哪些事 。
  • 相关阅读:
    ojdbc14.jar
    Redis
    ftl转成word
    Swagger
    SpringBoot
    条件注解
    Spring SpringMVC MyBatis
    Spring介绍
    Django_mysql表查询
    Django01
  • 原文地址:https://www.cnblogs.com/fejerry/p/8777184.html
Copyright © 2011-2022 走看看