ASP.NET 中 Session 实现原理浅析 [1] 会话的建立流程

Asp.net cookie session 原理 cookie不能储存过多信息,如果想保存大量的数据,可以保存一个Guid到cookie中,然后再服务器中建立以恶Guid为key,复杂数据为Value全局Dictionary、static字段对于不同用户也只有一份,因此用static实现多用户共享数据。Asp.net 已经内置了session机制,不要放太多的对象到session,session会有超时销毁的机制,发帖(服务器不可能知道浏览器是否再开着,什么时候关闭)asp.net 内置session使用。...... 阅读详情
HTTP 协议之所以能够获得如此大的成功,其设计实现的简洁性和无状态连接的高效率是很重要的原因。而为了在无状态的 HTTP 请求和有状态的客户端操作之间达到平衡,产生了服务器端会话 (Session) 的概念。客户端在连接到服务器后,就由 Web 服务器产生并维护一个客户端的会话;当客户端通过无状态 HTTP 协议再次连接到服务器时,服务器根据客户端提交的某种凭据,如 Cookie 或 URL 参数,将客户关联到某个会话上。这种思路在各种开发语言和开发环境中大量得到应用。
在 ASP.NET 中,Web 应用程序和会话状态被分别进行维护,通过 HttpApplication 和 HttpSessionState 分离 Web 应用程序与会话的功能。应用程序层逻辑在 Global.asax 文件中实现,运行时编译成 System.Web.HttpApplication 的实例;会话则作为单独的 System.Web.SessionState.HttpSessionState 实例,由服务器统一为每个用户会话维护,通过 ASP.NET 页面编译成的 System.Web.UI.Page 对象子类的 Session 属性访问。关于 ASP.NET 中不同层次关系可参考我以前的一篇文章《.NET 1.1中预编译ASP.NET页面实现原理浅析 [1] 自动预编译机制浅析》,以下简称【文1】。

ASP.NET 在处理客户端请求时,首先将根据客户端环境,生成一个 System.Web.HttpContext 对象,并将此对象作为执行上下文传递给后面的页面执行代码。
在【文1】的分析中我们可以看到,HttpRuntime 在处理页面请求之前,根据 HttpWorkerRequest 中给出的环境,构造 HttpContext 对象,并以次对象作为参数从应用程序池中获取可用应用程序。简要代码如下:
以下内容为程序代码:

private void HttpRuntime.ProcessRequestInternal(HttpWorkerRequest wr)
{
// 构造 HTTP 调用上下文对象
HttpContext ctxt = new HttpContext(wr, 0);

//...

// 获取当前 Web 应用程序实例
IHttpHandler handler = HttpApplicationFactory.GetApplicationInstance(ctxt);

// 调用 handler 实际处理页面请求
}




HttpApplicationFactory 工厂内部维护了一个可用的应用程序实例缓冲池,用户降低应用程序对象构造的负荷。
如果池中没有可用的应用程序对象实例,此对象工厂最终会调用 System.Web.HttpRuntime.CreateNonPublicInstance 方法构造新的应用程序实例,并调用其 InitInternal 方法初始化。详细步骤分析见【文1】
以下内容为程序代码:

internal static IHttpHandler HttpApplicationFactory.GetApplicationInstance(HttpContext ctxt)
{
// 处理定制应用程序
//...

// 处理调试请求
//...

// 判断是否需要初始化当前 HttpApplicationFactory 实例
//...

// 获取 Web 应用程序实例
return HttpApplicationFactory._theApplicationFactory.GetNormalApplicationInstance(ctxt);
}

private HttpApplication HttpApplicationFactory.GetNormalApplicationInstance(HttpContext context)
{
HttpApplication app = null;

// 尝试从已施放的 Web 应用程序实例队列中获取
//...

if(app == null)
{
// 构造新的 Web 应用程序实例
app = (HttpApplication)System.Web.HttpRuntime.CreateNonPublicInstance(this._theApplicationType);

// 初始化 Web 应用程序实例
app.InitInternal(context, this._state, this._eventHandlerMethods);
}

return app;
}



这里的 System.Web.HttpApplication.InitInternal 函数完成对应用程序对象的初始化工作,包括调用 HttpApplication.InitModules 函数初始化 HTTP 模块(后面将详细介绍),并将作为参数传入的 HttpContext 实例保存到 HttpApplication._context 字段中。而此 HTTP 上下文对象将被后面用于获取会话对象。
以下内容为程序代码:

public class HttpApplication : ...
{
private HttpContext _context;
private HttpSessionState _session;

public HttpSessionState Session
{
get
{
HttpSessionState state = null;
if (this._session != null)
{
state = this._session;
}
else if (this._context != null)
{
state = this._context.Session;
}
if (state == null)
{
throw new HttpException(HttpRuntime.FormatResourceString("Session_not_available"[img]/images/wink.gif[/img]);
}
return state;
}
}
}



而在 ASP.NET 页面中获取会话的方法也是类似,都是通过 HttpContext 来完成的。
以下内容为程序代码:

public class Page : ...
{
private HttpSessionState _session;
private bool _sessionRetrieved;

public virtual HttpSessionState Session
{
get
{
if (!this._sessionRetrieved)
{
this._sessionRetrieved = true;
try
{
this._session = this.Context.Session;
}
catch (Exception)
{
}
}
if (this._session == null)
{
throw new HttpException(HttpRuntime.FormatResourceString("Session_not_enabled"[img]/images/wink.gif[/img]);
}
return this._session;
}
}
}



在 HttpContext 中,实际上是通过一个哈希表保存诸如会话对象之类信息的
以下内容为程序代码:

public sealed class HttpContext : ...
{
private Hashtable _items;

public IDictionary Items
{
get
{
if (this._items == null)
{
this._items = new Hashtable();
}
return this._items;
}
}

public HttpSessionState Session
{
get
{
return ((HttpSessionState) this.Items["AspSession"]);
}
}
}



而 HttpContext.Session 所访问的又是哪儿来的呢?这就又需要回到我们前面提及的 HttpApplication.InitModules 函数。

在 .NET 安装目录 Config 子目录下的 machine.config 定义了全局性的配置信息,而 HttpApplication 就是使用其中 system.web 一节的配置信息进行初始化的。
以下内容为程序代码:

<system.web>
<httpModules>
<add name="OutputCache" type="System.Web.Caching.OutputCacheModule" />
<add name="Session" type="System.Web.SessionState.SessionStateModule" />
<add name="WindowsAuthentication" type="System.Web.Security.WindowsAuthenticationModule" />
<add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" />
<add name="PassportAuthentication" type="System.Web.Security.PassportAuthenticationModule" />
<add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" />
<add name="FileAuthorization" type="System.Web.Security.FileAuthorizationModule" />
<add name="ErrorHandlerModule" type="System.Web.Mobile.ErrorHandlerModule, System.Web.Mobile, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</httpModules>
</system.web>



httpModules 节点指定了 HttpApplication 需要初始化的模块列表,而在前面提到的 HttpApplication.InitModules 函数正式根据此列表进行初始化的
以下内容为程序代码:

private void HttpApplication.InitModules()
{
HttpModulesConfiguration cfgModules = ((HttpModulesConfiguration) HttpContext.GetAppConfig("system.web/httpModules"[img]/images/wink.gif[/img]);

if (cfgModules == null)
{
throw new HttpException(HttpRuntime.FormatResourceString("Missing_modules_config"[img]/images/wink.gif[/img]);
}
_moduleCollection = cfgModules.CreateModules();

for(int i = 0; i < _moduleCollection.Count; i++)
{
_moduleCollection[i].Init(this);
}

GlobalizationConfig cfgGlobal = ((GlobalizationConfig) HttpContext.GetAppConfig("system.web/globalization"[img]/images/wink.gif[/img]);
if (cfgGlobal != null)
{
_appLevelCulture = cfgGlobal.Culture;
_appLevelUICulture = cfgGlobal.UICulture;
}
}



Session 节点对于的 System.Web.SessionState.SessionStateModule 对象将被 HttpModulesConfiguration.CreateModules 方法构造,并调用其 Init 函数初始化。SessionStateModule 类实际上就是负责管理并创建会话,用户完全可以自行创建一个实现 IHttpModule 接口的类,实现会话的控制,如实现支持集群的状态同步等等。
SessionStateModule.Init 方法主要负责 machine.config 文件中的 sessionState 配置,调用 SessionStateModule.InitModuleFromConfig 方法建立相应的会话管理器。
以下内容为程序代码:

<system.web>
<sessionState mode="InProc"
stateConnectionString="tcpip=127.0.0.1:42424"
stateNetworkTimeout="10"
sqlConnectionString="data source=127.0.0.1;Integrated Security=SSPI"
cookieless="false"
timeout="20" />
</system.web>



sessionState 的使用方法请参加 MSDN 中相关介绍和 INFO: ASP.NET State Management Overview。关于不同 mode 的会话管理的话题我们后面再讨论,先继续来看会话的建立过程。

在从 machine.config 文件中读取配置信息后,InitModuleFromConfig 方法会向 HttpApplication 实例注册几个会话管理事件处理函数,负责在应用程序合适的情况下维护会话状态。
以下内容为程序代码:

private void SessionStateModule.InitModuleFromConfig(HttpApplication app,
SessionStateSectionHandler.Config config, bool configInit)
{
// 处理不使用 Cookie 的情况
//...

app.AddOnAcquireRequestStateAsync(new BeginEventHandler(this.BeginAcquireState),
new EndEventHandler(this.EndAcquireState));
app.ReleaseRequestState += new EventHandler(this.OnReleaseState);
app.EndRequest += new EventHandler(this.OnEndRequest);

// 创建会话管理器
//...
}



BeginAcquireState 和 EndAcquireState 作为一个异步处理器注册到 HttpApplication._acquireRequestStateEventHandlerAsync 字段上;OnReleaseState 则负责在合适的时候清理会话状态;OnEndRequest 则是 OnReleaseState 的一个包装,负责较为复杂的请求结束处理。前面提到的 HttpApplication.InitInternal 函数,在完成了初始化工作后,会将上述这些事件处理器,加入到一个执行队列中,由应用程序在合适的时候,使用流水线机制进行调用,最大化处理效率。有关 ASP.NET 中流水线事件模型的相关介绍,请参考 HTTP PIPELINES
Securely Implement Request Processing, Filtering, and Content Redirection with HTTP Pipelines in ASP.NET 一文中 The Pipeline Event Model 小节,有机会我在写文章详细分析。

知道了会话建立的调用流程再来看会话的实现就比较简单了,SessionStateModule.BeginAcquireState 被 HttpApplication 实例在合适的时候调用,处理各种会话的复杂情况后,使用 SessionStateModule.CompleteAcquireState 函数完成实际的会话建立工作,并将封装会话的 HttpSessionState 对象以 "AspSession" 为 key 加入到 HttpContext 的哈希表中,也就是前面提到的 HttpContext.Context 的由来。而 SessionStateModule.OnReleaseState 则从 HttpContext 中删除 "AspSession" 为 key 的 HttpSessionState 对象,并对会话管理器进行同步工作。

至此,ASP.NET 中的会话建立流程大概就分析完毕了,下一小节将进一步展开分析多种不同会话管理器的实现原理与应用。

实现Session跨域共享的ASP.NET示例 本文还有配套的精品资源,点击获取 简介:Web开发中,Session是存储用户会话信息的关键技术,但浏览器的同源策略限制导致默认不能跨域共享。本示例通过ASP.NET框架展示了如何在多个二级域名之间共享Session数据,增强用户体验。实现策略包括使用相同Cookie域、共享Session存储以及HTTP头部传递SessionID等。示例中还包括了安全性的考量和ASP.NE... 阅读详情

相关推荐

利用ArcGIS的模型构建器实现批量投影栅格和批量克里金插值

博主要批量投影几百个栅格,但是ArcGIS中的投影栅格的批处理工具需要手动一条条设置参数,还是麻烦,因此学习了使用模型构建器(ModelBuilder)来批量投影栅格,可以导入需投影栅格的文件夹,然后迭代投影,并按栅格原名逐个输出到指定目录。 1.在工具箱里构建模型 在arctool box里右键点击空白处,选择【添加工具箱】,点击ArcGIS默认工作目录的工具箱进行添加,然后Toolbox就会被添加到ArcToolbox页面,右键点击Toolbox,选择“新建”-“模型” 2.编写模型 (1).

qq_36958801的博客 1万+

ASP.NET 运行时详解 揭开请求过程神秘面纱

   对于ASP.NET开发,排在前五的话题离不开请求生命周期。像什么Cache、身份认证、Role管理、Routing映射,微软到底在请求过程中干了哪些隐秘的事,现在是时候揭晓了。抛开乌云见晴天,接下来就一步步揭开请求管道神秘面纱。 上篇回顾     在介绍本篇内容之前,让我们先回顾下上一篇《ASP.NET运行时详解 集成模式和经典模式》的主要内容。在上一篇随笔中,我们提到ASP.NE...

weixin_33721344的博客 201

零基础搭建机械零件检测系统:基于YOLOv8的PySide6可视化开发全攻略

本文详细介绍了如何从零开始搭建基于YOLOv8的机械零件检测系统,涵盖环境配置、数据集准备、模型训练优化及PySide6可视化界面开发全流程。通过实战案例展示YOLOv8在工业检测中的高效应用,帮助开发者快速实现自动化零件检测解决方案。

weixin_28455801的博客 309

ASP.NET的session操作方法总结

在开发ASP.NET程序时,需要对相关数据进行缓存,缓存较多的主要是用户的身份信息,现提供几个对session操作较为常用的方法: 1.添加session,对设置对应的时间: /// <summary> /// 添加Session,调动有效期为30分钟 /// </summary> ...

dfkqtok82472315的博客 386

实战避坑:在Ubuntu 22.04上配置NVIDIA GPU Direct RDMA时,必须搞清的P2P DMA与IOMMU那些事

本文深入探讨在Ubuntu 22.04上配置NVIDIA GPU Direct RDMA时P2P DMA与IOMMU的关键问题,解析PCIe架构中的地址转换、P2P DMA与标准DMA的区别,以及IOMMU对性能的影响。通过实战案例和调优建议,帮助用户避免常见配置陷阱,提升AI训练集群的数据传输效率。

weixin_33720078的博客 444

TI 实时操作系统SYS/BIOS使用总结

1:概述: SYS/BIOS 是一个可扩展的实时的操作系统。具有非常快速的响应时间(在中断和任务切换时达到较短的延迟),响应时间的确定性,强壮的抢占系统,优化的内存分配和堆栈管理(尽量少的消耗和碎片)。能够实现系统的模块化并可裁剪。 最大的特点就是:实时。 2:XDCtools: XDCtools 是SYS/BIOS引用的一种实时的软件组件技术(RTSC),它包括一些有用的工具,标准的AP

带头奋青的博客 5万+

无法向会话状态服务器发出会话状态请求 没有启动 ASP.NET State service错误的解决方法

<br />最近由于需要,又把放下的dotnet重新拾了起来。结果刚引了一个网站就报错如下:<br />无法向会话状态服务器发出会话状态请求。请确保已启动 ASP.NET State service,并且客户端和服务器端口是相同的。如果服务器位于远程计算机上,请检查 HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/aspnet_state/Parameters/AllowRemoteConnection 的值,确保服务器接受远程请求。 <br />说

goobycle 858

【数字逻辑电路课程设计】多功能数码管时钟VHDL+quartus II-EP1C12F324C8+源码+付费资源

我希望需要我这篇文章的是正常学习数字逻辑课程且正在设计数码管时钟的同学。我个人不推荐直接获取源代码,因此我另有一份付费资源是完整源代码;我推荐各位去研究我代码的逻辑尝试自己书写属于自己的代码,因此我保留了注释但隐去了变量。由于时间有限,我的设计不够完美,仍有很多缺陷,我将我的展望写在后面,各位可以尝试实现。我不为难同学,作为同学我理解各位设计的辛苦,因此如果有需要,私信我提供隐去敏感信息的学生证照片可直接获取源代码。

WannaFlysyx的博客 1534

未将对象引用设置到对象的实例 Microsoft.Office.Server.Administration.SqlSessionStateResolver

未将对象引用设置到对象的实例 Microsoft.Office.Server.Administration.SqlSessionStateResolver 错误  发生意外错误。  sharepoint网站在本地是一切正常的,不过当在外网链接它的时候,却报以上错误。 错户信息: Object reference not set to an instance of an object.

yl_99的专栏 4417

【突变检验方法一】MATLAB实现Pettitt突变检验

MATLAB实现Pettitt突变检验及贝叶斯突变检测等

WW、forever的博客 1万+

RK3588S之CPU--benchmark(一)

本章会基于RK3588S来介绍有关CPU常用的benchmark工具及测试过程

文艺小少年的博客 1499

ENS160传感器原理图设计,已量产(空气质量传感器)

ENS160 是一款集成式数字空气质量传感器,核心优势源于 “MEMS 传感元件 + 内置微处理器” 的架构。

不脱发的程序猿 571

转 ASP.NET 中 Session 实现原理浅析 [1] 会话的建立流程

HTTP协议之所以能够获得如此大的成功,其设计实现的简洁性和无状态连接的高效率是很重要的原因。而为了在无状态的HTTP请求和有状态的客户端操作之间达到平衡,产生了服务器端会话(Session)的概念。客户端在连接到服务器后,就由Web服务器产生并维护一个客户端的会话;当客户端通过无状态HTTP协议再次连接到服务器时,服务器根据客户端提交的某种凭据,如Cookie或URL参...

weixin_30781775的博客 140

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

ASP.NET 中 Session 实现原理浅析

<br /><br />    状态管理本来是一件很美好的事情,嘿嘿,只可惜总是有些厂商在实现的时候考虑得不那么周全。例如 MS 在 ASP 中的状态管理实现就比较烂,因为只实现了一个进程内的基于内存的状态管理,故而存在很多问题:<br /><br />    1.所有的 Session 数据都保存在 Web 服务的进程中,会造成服务器支持会话数量受到服务器内存资源的限制问题,同时也因为大量非活动会话导致内存被无效占用。<br />    2.服务器进程崩溃会导致所有的会话数据丢失。<br />    3.

lzh1160的专栏 433

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

ASP.NET页面对象 - Session

          获取 ASP.NET 提供的当前 Session 对象 ( HttpSessionState 类 )。该属性提供有关当前请求的会话的信息。为从 ASP.NET 应用程序请求页或文档的每个用户维护一个 Session 对象。当用户在应用程序中从一页移动到另一页时,存储在 Session 对象中的变量不会被放弃;相反,只要用户在应用程序中访问页,这些变量就将保持。一、ASP.N

dodream的专栏 4633

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

如何实现Asp与Asp.Net共享Session

在.net中,Session的存储机制已经与Asp的存储机制不一样,虽然可以在同一个IIS下同时运行asp与aspx,但是它们之间不能传递Session。   之前大批系统应用到了asp,在升级过程中,如果完全抛弃asp来重写,一来工作量太大,二来以前的成果不能保存下来。   所以微软提出了一个Session共享的解决方案,只是此文档光说明原理,并没有说具体的操作步骤,由此,我撰文描述过程。

移动开发与培训 637

ASP.NET Session 实现会话的建立流程

HTTP 协议之所以能够获得如此大的成功,其设计实现的简洁性和无状态连接的高效率是很重要的原因。而为了在无状态的 HTTP 请求和有状态的客户端操作之间达到平衡,产生了服务器端会话 (Session) 的概念。客户端在连接到服务器后,就由 Web 服务器产生并维护一个客户端的会话;当客户端通过无状态 HTTP 协议再次连接到服务器时,服务器根据客户端提交的某种凭据,如 Cookie 或 URL 参

272

asp.net Session的原理

以前只知道session 是存在cookie 的,具体是怎么回事 也说不清楚,面试有被问到了,所以 真的要好好的研究一下 原理这位大哥介绍的清楚了 http://blog.csdn.net/wangzhkai/article/details/4187496 做一个简单概括吧 cookie的两种类别 一种是会话性质的cookie,存放在浏览器内存中,当你在用代码向客户端写入coo...

dianpao0409的博客 292

Asp.net Session认识加强-Session究竟是如何存储你知道吗?

我们还是简单的来复习一下Session吧:Session的数据时保存在服务器端,并且每个客户端对应不同Session。那么Session究竟是如何保存,如何区分客服端的了?我们还是沿用以前的方法来讲吧,以一个demo开始: protected void Page_Load(object sender, EventArgs e) { string name

dz45693的专栏 3814

ASP.NET 中 Session 实现原理浅析 [2] 状态管理器

状态管理本来是一件很美好的事情,嘿嘿,只可惜总是有些厂商在实现的时候考虑得不那么周全。例如 MS 在 ASP 中的状态管理实现就比较烂,因为只实现了一个进程内的基于内存的状态管理,故而存在很多问题:    1.所有的 Session 数据都保存在 Web 服务的进程中,会造成服务器支持会话数量受到服务器内存资源的限制问题,同时也因为大量非活动会话导致内存被无效占用。    2.服务器进程崩溃会导致

杨义贤心灵驿站 597

Session的工作原理

session的工作原理 一直在使用session存储数据,一直没有好好总结一下session的使用方式以及其工作原理,今天在这里做一下梳理。这里的介绍主要是基于php语言,其他的语言操作可能会有差别,但基本的原理不变。 1.在php中如何操作session: session_start(); //使用该函数打开session功能 $_SESSION  //使用预定义全局变量操作数据 使用unset($_SESSION['key']) //销毁一个session的值 简单地操作,一切都是由服务器实现;由于处

zhiguo2010的专栏 2627
上一篇: Duwamish Web Services分析篇
下一篇: ASP.NET 中 Session 实现原理浅析 [2] 状态管理器
louisp
博客等级 码龄21年 5粉丝 44原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值