如何防止多个浏览器窗口在asp.net中共享同一个会话

时间:2010-03-25 16:52:28

标签: asp.net session browser cookies

我有ASP.net应用程序,它基本上是物理检查过程的数据输入屏幕。用户希望能够打开多个浏览器窗口并同时输入来自多个检查的数据。起初我使用的是基于cookie的会话,显然这已经爆发了。

我转而使用无cookie会话,这会话将会话存储在URL中,在测试中这似乎可以解决问题。每个浏览器窗口/选项卡都有一个不同的会话ID,输入的数据不会在另一个中输入数据。

然而,我的用户在打破事情方面比我预期的更有效率,似乎他们仍然设法在浏览器之间获得相同的会话。我认为他们正在将地址从一个标签复制/粘贴到另一个标签以打开应用程序,但我还没有能够验证它(它们位于另一个位置,所以我不能轻易地问他们)。

除了告诉他们不要复制和粘贴,或说服他们一次只输入一个,我怎样才能防止这种情况发生?

7 个答案:

答案 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>

基本上,这会在用户访问登录页面时首次设置窗口名称。登录后,对于每个后续页面加载,将测试窗口名称。

两个问题:

    如果JavaScript禁用
  • ,则
  • 不会出现问题
  • 如果用户错误地关闭了原始标签,然后在地址栏中粘贴了一些其他链接到我的网站,则用户将始终收到错误页面。为了让用户有机会恢复,我在SingleTab.htm页面中包含了“注销”链接,因此用户可以销毁他的会话cookie并开始新的会话。

答案 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中,就像你一样。