asp.net – 在Azure中的不同实例(可能在Web场中)中更改SessionID
我有一个带有一个WebRole的Azure项目有问题,但有多个实例使用无cookie会话.该应用程序不需要会话存储,因此它不使用任何会话存储提供程序,但我需要跟踪SessionID.显然,the SessionID should be the same accross the WebRole instances,但它突然变化没有解释.我们使用SessionID来跟踪一些数据,因此非常重要.
为了重现这个问题: >创建云项目. <p><%= Session.SessionID %></p> <asp:Button ID="Button1" runat="server" Text="PostBack" onclick="Button1_Click" /> >为按钮添加一个事件处理程序,它会稍微延迟响应: protected void Button1_Click(object sender,EventArgs e) { System.Threading.Thread.Sleep(150); } >打开Web.Config <system.web> <sessionState cookieless="true" /> </system.web> >运行项目,快速点击“PostBack”按钮一段时间,注意地址栏中的会话ID.什么都没发生,会话ID始终是相同的:).停下来. <Instances count="4" /> >确保在Web.config中有一行与Visual Studio自动添加的机器密钥相关联. (在system.web的末尾). 为什么会这样?据我所知,如果所有机器共享machineKey,则会话应该是相同的.使用cookie没有问题,问题显然是在使用无cookie会话时. 我最好的猜测是,当存在多个实例时,当一个WebRole中生成的SessionID转到另一个时,会被拒绝并重新生成.这没有意义,因为所有的WebRoles都有相同的machineKey. 为了找出问题并更清楚地看到它,我创建了自己的SessionIDManager: public class MySessionIDManager : SessionIDManager { public override string CreateSessionID(HttpContext context) { if (context.Items.Contains("AspCookielessSession")) { String formerSessionID = context.Items["AspCookielessSession"].ToString(); // if (!String.IsNullOrWhiteSpace(formerSessionID) && formerSessionID != base.CreateSessionID(context)) // Debugger.Break(); return formerSessionID; } else { return base.CreateSessionID(context); } } } 并使用它在WebConfig中更改此行: <sessionState cookieless="true" sessionIDManagerType="WebRole1.MySessionIDManager" /> 现在你可以看到SessionID不会改变,无论你打多快多快.如果取消注释这两行,您将看到ASP.NET如何创建新的sessionID,即使已经存在. 为了强制ASP.NET创建新会话,只需重定向到站点中的绝对URL: Response.Redirect(Request.Url.AbsoluteUri.Replace(Request.Url.AbsolutePath,String.Empty)); 为什么这个事情发生在无cookie会话中? 我在MySessionIDManager中的解决方案有多可靠? 亲切的问候. 更新: >我尝试过这种解决方法: public override bool OnStart() { // For information on handling configuration changes // see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357. using (var server = new ServerManager()) { try { // get the site's web configuration var siteNameFromServiceModel = "Web"; // update this site name for your site. var siteName = string.Format("{0}_{1}",RoleEnvironment.CurrentRoleInstance.Id,siteNameFromServiceModel); var siteConfig = server.Sites[siteName].GetWebConfiguration(); // get the appSettings section var appSettings = siteConfig.GetSection("appSettings").GetCollection() .ToDictionary(e => (string)e["key"],e => (string)e["value"]); // reconfigure the machine key var machineKeySection = siteConfig.GetSection("system.web/machineKey"); machineKeySection.SetAttributeValue("validationKey",appSettings["validationKey"]); machineKeySection.SetAttributeValue("validation",appSettings["validation"]); machineKeySection.SetAttributeValue("decryptionKey",appSettings["decryptionKey"]); machineKeySection.SetAttributeValue("decryption",appSettings["decryption"]); server.CommitChanges(); _init = true; } catch { } } return base.OnStart(); } >我也在put a void Session_Start(object sender,EventArgs e) { Session.Add("dummyObject","dummy"); } 赏金! 解决方法
简而言之,除非您使用cookie或会话提供程序,否则会话ID无法从一个Web角色实例传递到另一个Web角色实例.您提到的帖子表示,如果您不使用Cookie或会话存储,则SessionID不会在Web角色中保持不变.
检查此 previous question以了解处理Azure中的状态存储的方法,例如使用表存储 machineKey与会话或应用程序域无关,它是用于encrypt,decrypt,validate身份验证和查看状态数据的密钥.要使用Reflector验证此打开的SessionIDManager.CreateSessionID.您将看到ID值只是一个随机的16字节值,编码为字符串. SessionIDManager已经在GetSessionID方法中检查了AspCookielessSession值,而不是CreateSessionID,因此在代码执行之前检查已经完成.由于默认的会话状态模式是InProc,因此单独的Web角色将无法验证会话密钥,因此它们会创建一个新的. 事实上,角色可以随时迁移到不同的物理机器,在这种情况下,它的状态将会丢失.来自SQL Azure团队的这篇文章正是出于这个原因描述了一种到use SQL Azure to store state的方法. 编辑我终于让TableStorageSessionStateProvider在无cookie模式下工作! 虽然TableStorageSessionStateProvider通过覆盖SessionStateStoreProviderBase.CreateUnititializedItem确实支持cookieless模式,但它无法在私有SessionStateStoreData GetSession中正确处理空会话(HttpContext上下文,字符串id,out bool锁定,out TimeSpan lockAge,out对象lockId,out SessionStateActions操作,bool独占).如果在底层blob存储中找不到数据,解决方案是返回一个空的SessionStateStoreData. 该方法长145行,所以我不会在这里粘贴它.搜索以下代码块 if (actions == SessionStateActions.InitializeItem) { // Return an empty SessionStateStoreData result = new SessionStateStoreData(new SessionStateItemCollection(),} 创建新会话时,此块将返回空会话数据对象.不幸的是,空数据对象没有存储到blob存储器中. 如果blob为空,则使用以下行替换第一行以使其返回空对象: if (actions == SessionStateActions.InitializeItem || stream.Length==0) 只要提供程序支持,就可以使用long stroy short cookieles会话状态.您必须决定使用示例提供程序是否使用无cookie状态.也许vtortola应该检查AppFabric Caching CTP.它包括开箱即用的ASP.NET提供程序,速度要快得多,它肯定比示例提供程序有更好的支持.关于如何设置会话状态甚至还有step-by-step tutorial. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- asp.net-mvc-3 – 如何将int数组传递给RouteValueDictionar
- asp.net – SSRS ReportViewer Web Control – 渲染为异步时
- asp.net – 多个选择列表框而不按CTRL
- asp.net-mvc-3 – 使用ViewModel时不显示MVC3自定义验证错误
- asp.net-mvc – ASP.NET Actionlink与glyphicon和文本与不同
- asp.net-mvc – 如何在ASP.NET MVC中生成弹出页面链接
- Asp.Net System.Web.Routing查找实际的.aspx页面
- asp.net-mvc – RenderPartial从另一个控制器(和在另一个文
- asp.net-mvc – ASP.NET MVC模型在编辑器模板中绑定IList
- C#如何根据类的名词创建类的实例
- EF数据库初始化策略及种子数据的添加
- asp.net-mvc – 使用AD的ASP.NET MVC表单Auth在本
- 使用.NET Class作为SSRS RDLC的数据源
- asp.net-mvc – 在ASP.NET MVC中下载动态生成的文
- asp.net-mvc – 寻找第三方CMS与MVC网站集成
- asp.net-mvc – 有没有办法用asp.net mvc Razor
- asp.net-mvc – 如何在ASP.NET MVC中提供自己的I
- 在动作之外执行异步操作asp.net mvc
- asp.net-mvc-3 – 无法添加从其他类继承的模型的
- asp.net-mvc – 如何从强类型视图中隐藏实体框架