我继承了一个旧的ASP.Net Webforms应用程序,该应用程序大量使用Session变量来存储用户提交的应用程序的数据库记录ID。这导致了一些严重的问题,即用户在多个选项卡中为不同的应用程序打开表单,无意中在一个应用程序中覆盖信息,而数据意味着另一个应用程序。
整个应用程序的常见用法如下所示:
// Get the application ID from the database
var appID = Convert.ToInt32(Session["appID"]);
// Update application using the above ID
UpdateDB("UPDATE Application SET Title='MY TITLE' WHERE id=" + appID);
// Redirect to another step of the form
Response.Redirect("/application/step-2");
由于此问题在应用程序的多个页面中仍然存在,因此我发现的解决方案不太理想(详见本文末尾)。
我的问题:有没有办法阻止新标签覆盖现有会话变量,而不必在整个应用程序中重写会话访问权限?
以下是我发现的解决方案,由于需要更改多少应用程序而不是最后的解决方案:
将ViewState("_PageID")
添加到会话变量
使用无Cookie会话(存储在网址中)
*以上解决方案见于相关帖子:asp.net - session - multiple browser tabs - different sessions?
答案 0 :(得分:1)
听起来AppID在逻辑上不是会话的属性。它是页面的属性,也可能是工作流程的属性。
如果你需要存储在回发之间存在的页面属性,你可以像这样存储它:
this.ViewState["AppID"] = appID;
并执行更新
var appID = (int)ViewState["appID"]
UpdateDB("UPDATE Application SET Title='MY TITLE' WHERE id=" + appID);
请确保secure your ViewState或其他恶意用户可以篡改AppID并更新其他人的记录。
ViewState存储在页面本身中,因此不会在选项卡之间泄漏。
答案 1 :(得分:1)
听起来重写代码以便在会话以外的地方存储数据是不可行的。
如果确实如此,也许您最简单的选择是在您的网站上添加代码,以便在用户在第二个标签页中打开网站时显示错误,或者如果其他标签中的活动修改了AppID。
这是一种方法,高级别:
向Application_EndRequest添加代码,以输出包含每个页面的时间戳或随机随机数的“microsession”cookie。注意:您必须小心,不要输出此cookie用于资源请求,例如图像或CSS。仅在当前请求针对页面时输出。
将一段javascript添加到您的common.js文件中(或任何位置会导致它为您网站中的每个页面运行),该文件执行以下操作:
一个。在页面加载时,抓取microsession cookie并将其值存储在Javascript变量
中湾偶尔检查microsession cookie以查看它是否已更改。您可以使用计时器执行此操作,也可以只检查用户何时提交任何表单。请注意,当选项卡失去焦点时,某些设备会暂停脚本,因此如果您使用计时器,还应检查选项卡何时再次获得焦点。
℃。如果cookie已更改,则表示用户从您的站点请求了一个页面,但在另一个选项卡中。显示错误。此时,您可以强制他们注销或仅Session.Abandon()
并将其重定向到主页,在主页上将自动为他们构建一个新的干净会话。
如果要允许多个选项卡,并且只想在AppID发生意外更改时导致错误,可以将microsession cookie设置为AppID的哈希值而不是nonce。这样,只有在AppID发生变化时才会触发错误。如果你需要检查多个会话变量,你可以在生成哈希之前连接它们(字符串连接很好)。