我有ASP.net应用程序,它基本上是物理检查过程的数据输入屏幕。用户希望能够打开多个浏览器窗口并同时输入来自多个检查的数据。起初我使用的是基于cookie的会话,显然这已经爆发了。
我转而使用无cookie会话,这会话将会话存储在URL中,在测试中这似乎可以解决问题。每个浏览器窗口/选项卡都有一个不同的会话ID,输入的数据不会在另一个中输入数据。
然而,我的用户在打破事情方面比我预期的更有效率,似乎他们仍然设法在浏览器之间获得相同的会话。我认为他们正在将地址从一个标签复制/粘贴到另一个标签以打开应用程序,但我还没有能够验证它(它们位于另一个位置,所以我不能轻易地问他们)。
除了告诉他们不要复制和粘贴,或说服他们一次只输入一个,我怎样才能防止这种情况发生?
答案 0 :(得分:5)
考虑使用ViewState而不是Session,因为ViewState将状态信息呈现给客户端(HTML页面)。我不确定您是否能够对浏览器的会话行为进行详细控制,因为会话ID由浏览器按照制造商的方式进行维护。因此,ViewState更具可预测性,不仅适用于未来的浏览器版本。
答案 1 :(得分:3)
这是一个非常好的问题,我也经常思考这个问题。
将您的主网页存储在iframe中。使用javascript检查您的网页是否仍在父iframe中。如果没有,那么他们已经打开了多个浏览器窗口。
您需要确保整个应用都是iframe友好的。
答案 2 :(得分:3)
我不确定为什么您希望限制会话只处理一个检查过程,然后强制多个会话以便用户在多个检查中同时工作。这感觉就像一种相当尴尬的孤立风格。
Web应用程序(和页面)应该能够在单个用户会话中处理多个检查过程。
对于单一处理,不应明确公开Session变量中保存的任何数据。它们应该存储在集合中,以便轻松识别哪组数据属于哪个检查过程。 每个页面提交回Web服务器应该带有一个与其相关的检查过程的标识符,以便匹配并提取正确的会话集以供使用。
伪代码概念
var inspectionID = this.inspectionLabel.Text;
var inspectionSets = (Hashtable)Session["inspections"];
var inspection = (Inspection)inspectionSets[inspectionID];
答案 3 :(得分:2)
用户是否必须使用其他帐户登录才能访问不同的物理检查?在我看来,只要PhysicalInspectionID
是URL的一部分,那么同时编辑多个物理检查应该没有问题。
,例如,
http://inspections.mydomain.com/edit/23
当然,如果他们复制了URL,他们将获得另一个窗口的副本,但这将告诉他们不要这样做。相反,他们打开另一个窗口并通过UI浏览到正确的检查(或添加一个新的)。
答案 4 :(得分:2)
这是我在ASP.NET MVC中使用的,禁止经过身份验证的用户打开多个标签:
<script language="javascript" type="text/javascript">
@if(Request.IsAuthenticated)
{
<text>
if (window.name != 'singleWindow') {
window.location.href = "Content/ErrorPages/SingleTab.htm";
}
</text>
}
else
{
<text>
window.name = "singleWindow";
</text>
}
</script>
基本上,这会在用户访问登录页面时首次设置窗口名称。登录后,对于每个后续页面加载,将测试窗口名称。
两个问题:
答案 5 :(得分:2)
可以通过以下方式实现该问题的解决方案:
public static class CommonHelper
{
public static bool SiteGuard
{
get
{
if(HttpContext.Current.Session["SiteGuard"] == null)
return true;
return (bool)HttpContext.Current.Session["SiteGuard"];
}
set
{
HttpContext.Current.Session["SiteGuard"] = value;
}
}
}
public partial class TestPage : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if(!Page.IsPostBack)
{
bool go = false;
for(int i = 0; i < 50; i++) // wait for the service to work (5 secs max)
{
if(CommonHelper.SiteGuard)
{
go = true;
break;
}
Thread.Sleep(100);
}
if(!go)
Response.Redirect("Login.aspx");
SiteGuard = false; // from now on, nobody can visit your site
}
// Now as long as Page.IsPostBack is true you are in a good shape
}
}
将asmx Web服务(或您认为合适的任何其他类型的服务)添加到根项目中,并向其添加以下方法:
[WebMethod(EnableSession = true)]
public void FreeSiteGuard()
{
HttpContext.Current.Session["SiteGuard"] = null;
}
在母版页或每个页面上添加以下javascript:
<script type="text/javascript">
window.onbeforeunload = function (e) {
e = e || window.event;
if (e) {
// Invoke web service
YourProject.YourWebServiceName.FreeSiteGuard();
}
};
</script>
请注意,您的网站响应时间会受到网络服务速度的影响。
答案 6 :(得分:0)
请求没有referer时创建一个新的sessionId。 这解决了复制粘贴网址问题。 将sessionId存储在url中,就像你一样。