zoukankan      html  css  js  c++  java
  • ASP.NET 状态管理(cookie、Session)

    cookie

           自定义 cookie 提供了保存备用数据的另一个选择。cookie 在用户的硬盘上创建一个小文件(临时 cookie 保存在 Web 浏览器的内存)。

           cookie 的优点

    1. 对用户透明,他们不必知道需要保存哪些信息。
    2. 很方便的由应用程序中的任意页面使用,甚至还可以保存很久以便在不同的访问中使用。

           cookie 的限制

    1. 和查询字符串一样,只能使用简单的字符串信息
    2. 如果用户找到并打开cookie文件,它们很容易被修改。因此不适合保存复杂,私有的信息或者大量的数据。
    3. 部分用户还会禁用 cookie,不过大部分情况下用户会接受 cookie,因为它们被太多的站点使用。

           cookie 的使用

    1. Request 对象和 Response 对象都提供了 Cookies 集合。
    2. 使用 Request 对象读取 cookie
    3. 使用 Reesponse 对象设置 cookie
    HttpCookie cookie = new HttpCookie("Preferences");      
    cookie["Language"] = "English";
    cookie["Country"] = "US";
    Response.Cookies.Add(cookie);

           用这种方式添加的 cookie 在每次请求时都会回发,它直到用户关闭浏览器时才会消失。但我们可以设置过期时间来设置长期存在的 cookie(以临时 Internet 文件的形式存在用户硬盘上)。

    // This cookie lives for one year.
    cookie.Expires = DateTime.Now.AddYears(1);

           使用 Request.Cookies 集合通过 cookie 的名字来读取 cookie:

    HttpCookie cookie = Request.Cookies["Preferences"];
     
    // because the user could disable cookie,so must check it
    string language;
    if (cookie != null)
    {
        language = cookie["language"];
    }

           移除 cookie 的唯一方法是使用一个已过期的 cookie 来替换它:

    HttpCookie cookie = new HttpCookie("LanguagePref");
    cookie.Expires = DateTime.Now.AddYears(-3);
    Response.Cookies.Add(cookie);

    会话状态 Session

           会话状态时状态管理最重要的一部分!通过它你可以在一个页面存储数据而另一个页面获取数据,最重要的是它还支持包括自定义数据类型在内的任意对象类型。每个访问应用程序的客户端都有不同的会话且包含不同的信息,因此 Session 是跨页浏览时保存用户购物车内容的理想场所

           Session 不是免费的,它迫使 Web 服务器在服务器内存中保存额外的信息,即使信息量很小,成百上千个用户访问网站时也很可能会迅速造成一场灾难。

    会话架构

           ASP.NET 使用一个唯一的 120 位标识符跟踪会话,并使用一个私有的算法来生成这个值,从统计学上说可以保证这个值是唯一的且足够随机,从而恶意用户不能反向设计或猜出指定用户将要使用的值。

           这个值是客户端和服务器端传递的唯一值。客户端发送会话 ID 后,ASP.NET 查找相应的会话,从状态服务器获得序列化的数据并将其转换为活动的对象,最后将这些对象放到可以用代码访问的集合,这个过程是自动完成的。

           我们知道,ASP.NET 处理 HTTP 请求时会经过一个包含不同模块的管道链,这些模块可以响应应用程序事件。链上的一个模块是 SessionStateModule(在 System.Web.SessionState 命名空间中)

           SessionStateModule 模块负责产生会话 ID,从外部提供程序中获取会话数据,并把数据绑定到请求的上下文中。页面处理完毕后,该模块还会保存会话信息。但很重要的一点要明白,SessionStateModule 并不保存会话数据,而是会话状态持久化在外部组件中,这些外部组件称为状态提供程序

           会话状态时 ASP.NET 可插拔架构的另一个例子。状态提供程序是可以实现 IHttpSessionState 接口的任意类,也就是说构建(或购买)一个新的 .NET 组件,你就可以自定义如何处理会话状态。

           ASP.NET 有 3 个预建的状态提供程序,它们允许你在 进程独立服务(windows服务)SQL Server数据库 中保存信息。

    使用会话状态

           可以通过 System.Web.SessionState.HttpSessionState 类和会话状态交互,它建立在 Session 对象中,由 ASP.NET 网页提供。

           会话状态在下面这些情形下会丢失:

    1. 用户关闭并重启浏览器
    2. 用户通过另一个浏览器访问同一页面(不同浏览器处理这一方式是不同的)
    3. 没有活动导致会话超时,默认情况下,闲置 20 分钟后会话会超时
    4. 程序员调用 Session.Abandon()方法结束会话

           在前2种情况下,会话其实还保存在服务器的内存中,Web 服务器并不知道用户已经关闭了浏览器或者更换了窗口,会话在内存中游荡,但由于不能访问到,直至最终过期。此外应用程序域重建时会话也会丢失,这个过程透明的发生。

    HttpSessionState 成员

    Count 当前会话集合中的项目数
    IsCookieless 指示当前会话是存储在 cookie 中还是嵌入在修改的 URL 中
    IsNewSession 指示会话是否是只为当前请求而创建的
    Mode 一个枚举值,用于指示 ASP.NET 如何保存会话状态信息
    SessionID 当前客户端的会话标识字符串
    StaticObjects 通常不使用(为了向后兼容 ASP 程序的)
    Timeout 超时的时长,该值可以通过代码修改
    Abandon() 立即取消当前会话并释放它占用的全部内存空间,退出页面时很有用,确保服务器内存得到快速重用
    Clear() 不改变当前会话标识符的情况下清空所有的会话项目

    配置会话状态

           可以通过 web.config 文件中的 <sessionState> 元素为应用程序配置会话状态,下面是所有可用设置的一个快速浏览:

    <system.web>
    <!-- Other settings omitted-->
     
    <sessionState
         mode="Off|InProc|StateServer|SQLServer|Custom"
         stateConnectionString="tcpip=127.0.0.1:42424"
         stateNetworkTimeout="10"
         sqlConnectionString="data source=127.0.0.1;Integrated Security=SSPI"
         sqlCommandTimeout="30" allowCustomSqlDatabase="false"
         useHostingIdentity="trye|false"
         compressionEnabled="true|false"
         cookieless="UseCookies" cookieName="ASP.NET_SessionId"
         regenerateExpiredSessionId="true|false"
         timeout="20"
         customProvider=""
      />
    </system.web>

    1. Mode

           模式设置允许你配置在请求间保存会话状态信息的会话状态提供程序

           Off

                  禁用应用程序中所有页面的会话状态管理

           InProc

                  类似于传统 ASP 中保存会话的方式,它指示 ASP.NET 在当前应用程序域中保存信息。这种方式有最好的性能却具有最差的持久性,如果重启服务器,状态信息将丢失。InProc 是默认选项,它对于多数小型网站有意义,不过在 Web 集群中根本不能工作。你需要使用 SQL Server 状态服务才能使会话状态在服务器间共享。另一个不使用它的原因是它会产生较多的会话碎片。ASP.NET 应用程序会因为多种活动而回收,包括更改配置,更新页面,如果你发现你的应用程序域不断重启而导致会话过早丢失,你可以选择另一种更强健的会话状态提供程序

    使用进程外或 SQL Server状态服务时,请记住你需要考虑更多的问题:

    • 使用 StateServer 或 SQLServer 模式时,要保存在会话状态中的对象必须是可序列化的,否则 ASP.NET 不能够将对象传送到状态服务器或保存到数据库中
    • 如果在集群中,则需要一些额外的配置以保证所有 Web 服务器同步,否则服务器会采用不同的方式编码会话状态信息,当用户由一台服务器路由到另一台服务器时会产生一个问题,解决该问题的办法是修改 machine.config 文件的 <machineKey>节以确保所有服务器使用相同的设置。
    • 如果不使用进程内的状态提供程序,SessionStateModule.End 事件就不会触发,所有 global.asax或者HTTP模块中所有注册该事件的处理程序将被忽略

           StateServer

                  采用该选项时 ASP.NET 使用一个独立的 Windows 服务来管理状态。即使该服务于 Web 服务器在同一台服务器上。它也会在 ASP.NET 主进程外加载,这样当 ASP.NET 进程需要重启时,可以为状态提供基本的保护。代价是两个进程间传递信息时将导致延迟,如果频繁访问和更改状态信息,则速度会明显变慢,让人无法忍受

                  使用 StateServer 选项时,要为 StateConnectionString 设置一个值。该值定义了运行服务的计算机的 TCP/IP 地址和端口号。当然,在应用程序能够使用服务之前必须将其启动。

                  使用 StateServer 选项时还可以设置一个可选的 stateNetworkTimeout 特性,该特性指定放弃请求前等待服务器响应的最大秒数,默认值是 10 秒。

    image

           SQL Server

                  该选项指示 ASP.NET 使用 sqlConnectionString 特性设定的 SQL Server 数据库保存会话信息。这是目前最具弹性同时也是目前最慢的状态存储方式,使用该模式需要一台装有 SQL Server 的服务器。设置 sqlConnectionString 时通常需要指定数据源(服务器地址),除非使用 SQL 整合安全方式,否则还要指定用户名和密码。此外,还需要安装临时会话数据库和一些特定的存储过程。其中存储过程负责保存和获取会话信息。

                  ASP.NET 使用命令行工具 aspnet_regsql.exe 实现这一目的。使用 aspnet_regsqt.exe 创建会话存储数据库时,要提供 -ssadd 参数,此外,使用 -S 参数表明数据库服务器的名称,-E 参数使用当前登录的 Windows 用户账户登录数据库。使用 -ssremove 参数可以移除 ASPState 数据库

    这个命令在当前计算机上创建会话存储数据库,使用默认的数据库名称 ASPState:

    aspnet_regsql.exe -S localhost -E -ssadd

    这个命令使用了假名 localhost ,它告诉 aspnet_regsql.exe 连接当前计算机上的数据库服务器,可以用数据库服务器所在的计算机名替代它。

                  标准会话状态超时时间也对 SQL Server 状态管理有效。因为 aspnet_regsql.exe 工具同时还创建了一个名为 ASPState_Job_DeleteExpiredSessions 的新 SQL Server 执行计划。只要 SQLServerAgent 服务在运行,这个执行计划每分钟执行一次。

                  此外,每次重启 SQL Server 时状态表会被删除,无论会话是否超时。这是因为此表是创建在 tempdb 数据库里,它是一个临时的存储区域。如果这不是你所期望的行为,你可以告诉 aspnet_regsql.exe 在 ASPState 数据库里安装持久状态表。这是可以使用参数 -sstype p(Persisted)

    aspnet_regsql.exe -S localhost -E -ssadd -sstype p

    现在,会话记录将保存在数据库里,即便重启了 SQL Server 也是如此。

                  最后一个选项是是创建一个非默认的状态表,这时使用参数 -sstype c(Custom),并通过 -d 参数提供数据库名称。

    aspnet_regsql.exe -S localhost -E -ssadd -sstype c -d MyCustomStateDb

    采用这种方法创建的是持久会话表。

                  如果使用了自定义数据库,还需要对 web.config 做两处微调:

    <sessionState mode="SQLServer" allowCustomSqlDatabase="true" sqlConnectionString=
        "data source=localhost;Integrated Security=SSPI;Initial Catalog=MyCustomStateDb" />

           Custom

                  使用自定义模式时,需通过 customProvider 特性指定会话状态存储提供程序。这个特性指向 App_Code 文件夹中一个类的名字,或者在 Bin 目录或 GAC 中某个已编译的程序集的名字。创建自定义状态提供程序是一项需要小心处理的底层任务,需要保证安全性,稳定性和可扩展性,因此最好由可靠的第三方设计和测试

    2. 压缩

           他可以减小序列化会话数据的大小。把 enableCompression 设置为 true 后,会话数据在传送到进程外会话状态存储时才起作用,因为这种情况下数据才会被序列化。

           会话数据是使用 System.IO.Compression.GZipStream 类自动进行压缩的。

           会话状态压缩最有意义的两个场景如下:

    • 在内存里存储了大量会话状态数据时:Web服务器内存是非常珍贵的资源。理想情况下,会话状态用于少量的信息段,后端数据库处理大量数据的长期储存。但如果情况不是这样并且进程外状态服务器拥有大量的内存,压缩式潜在的解决方案。
    • 在其他计算机存储会话状态数据时:在某些大型的 Web 应用程序中会话状态是在进程外的(一般是 SQL Server)并且在单独的计算机上。因此,ASP.NET 需要在网络连接上传送会话信息。显然,这样的设计降低了执行速度,不过,对于某些需要大量存储会话状态信息且流量非常大的网站而言,这仍然是最佳的折中方案。

           第一种情况,压缩牺牲了 CPU 的时间换取了Web服务器内存。

           第二种情况,压缩牺牲了 CPU 的时间节省了网络流量。

    注:

           实际的压缩量由于数据类型的不同差异很大,但在微软的测试中,客户端得到 30% 到 60% 的数据减少,在这些场景中它确保了性能的极大提升。

    3. cookieless

           HttpCookieMode 枚举值:

    UseCookies 无论浏览器或设备是否禁用 cookie,总是可以使用 cookie(默认选项)。
    如果设备不支持 cookie,后续的请求会话信息会丢失,因为每次请求都会获得新的标识符
    UseUri 无论浏览器或设备是否支持 cookie,都不会使用 cookie。会话ID被存储在URL中。
    UseDeviceProfile ASP.NET 通过检查 BrowserCapabilities 对象来决定是否使用无 cookie 会话。
    (只指明了设备应当支持的---而没有考虑用户可能禁用了浏览器中的 cookie)
    AutoDetect ASP.NET 通过尝试设置和读取cookie(一种常用的 Web 技术)来确定浏览器是否支持 cookie
    该技术可以正确判断浏览器是否支持 cookie 但却禁用了 cookie,在这种情况下,将使用无 cookie 会话。

           使用无 cookie 模式时,例如下面这样:

    <sessionState cookieless="UseUri" 。。。>

           会话 ID 会自动插入到 URL 中,ASP.NET 获得请求时,它将移除 ID,检索会话集合,将请求送到相应的目录:

    http://localhost/WebApplication/(amfdddgd677sdgfdfg)/Page.aspx

           因为会话 ID 是插入到 URL 中的,所以相对链接也会自动获得会话 ID,真正限制无 cookie 会话状态的是:不能使用绝对链接,因为他们不包含会话 ID

           ASP.NET 默认允许重用会话标识。如果使用了一个含有过期会话的查询字符串,ASP.NET 会用这个 ID 重新创建一个会话。问题是某个会话 ID 会不经意的出现在某些公共场合,例如作为搜索引擎的查询结果。这样多个用户会使用同样的会话 ID 来访问服务器并加入到含有相同共享数据的相同会话中。为避免这一潜在的安全问题,使用无 cookie 会话时,推荐加入可选的 regenerateExpiredSessionId 特性,并把该值设为 true。这样当用户使用已经过期的会话 ID 时,会创建一个新的会话 ID。这么做的唯一缺点是,当前页面所有视图状态和表单数据将全部丢失,因为 ASP.NET 执行了一次重定向来保证浏览器使用新的会话 ID

           可以通过 Session 对象的 IsCookieless 属性来检查当前是否在使用无 cookie 的会话。

    4. timeout

           这个设置体现了会话状态最重要的折中。不同的分钟数会给服务器负载及应用程序性能带来非常大的影响。理想状态下,最佳的时间应当足够短,保证服务器内存能及时释放,同时这个时间也应该足够长,保证客户端在暂停一段时间后会话不会丢失还能继续使用。

           可以在代码中设置:

    Session.Timeout = 10;

    会话状态安全

           会话状态中的信息非常安全,因为它们只保存在服务器上。然而含有会话 ID 的 cookie 可能很容易被篡改。就是说一个恶意用户可以偷走 cookie 然后在另一台计算机上继续使用。

           一个常用的方法是使用自定义的会话模块来检查客户端 IP 地址的变化。唯一真正有效的方法是仅在使用了 SSL 的网站上使用会话 cookie。采用这种方法,会话 cookie 被加密从而在其他计算机上不可用。如果使用这种方式,将会话 cookie 标识为安全 cookie 才有意义,这样 cookie 只能通过 SSL 连接传送。这使得用户不能将 URL 由 https:// 修改为可以不使用 SSL 发送 cookie 的 http:// 。

    Request.Cookies["ASP.NET_SessionId"].Secure = true;  // 这样的 cookie 必须在使用了 SSL 的网站上传送

    这条代码应在用户通过验证后立即使用,另外还要确保会话状态中至少有一点信息,这样它才不被取消。

  • 相关阅读:
    如何理解Stand SPI Dual SPI 和Quad SPI??
    一款很实用的欠压过压保护电路
    AbpZero之企业微信登录(拓展第三方auth授权登录)第三步:需要注意事项
    在AbpZero中hangfire后台作业的使用——开启hangfire
    AbpZero之企业微信登录(拓展第三方auth授权登录)第一步:查看AbpZero的auth第三方登录的底层机制
    在AbpZero中hangfire后台作业的使用——hangfire的调度
    AbpZero后台模块化(1)
    AbpZero之企业微信登录(拓展第三方auth授权登录)第二步:开始逐步实现企业微信登录
    vue基础(入门视频零基础精华总结)
    组件参数校验与非props特性
  • 原文地址:https://www.cnblogs.com/SkySoot/p/2590117.html
Copyright © 2011-2022 走看看