【问题标题】:Redirecting to another page on Session_end event在 Session_end 事件上重定向到另一个页面
【发布时间】:2013-09-05 02:59:02
【问题描述】:

我想在会话超时时自动重定向到登录页面。

在 web.config 文件中,我有以下代码

<configuration>
    <system.web>
       <sessionState mode="InProc"  timeout="1"/>
    </system.web>
</configuration>

在 Global.asax 文件中-

protected void Session_End(object sender, EventArgs e)
{
    Response.Redirect("LoginPage.aspx");
}

但超时后,我收到以下错误:

HttpException 未被用户代码处理。

响应在此上下文中不可用。

有解决这个问题的线索吗?

【问题讨论】:

  • 您应该在身份验证元素中执行此操作。而不是在代码中。
  • 当您说会话超时时重定向到登录页面时,您的意思是您希望浏览器(客户端)从服务器事件触发自动重定向吗?如果是这样,这将需要的不仅仅是服务器代码,更多的是使用 SignalR 集线器来触发客户端 javascript 重定向
  • 据我所知,Session_End 事件不会作为请求的一部分触发。当超时发生时,它会在后台触发。下次用户回来时,他将自动获得一个新会话,因为旧会话已超时。因此,当Session_End 事件发生时,当前没有可以重定向的Response...
  • 这个related question 可能有帮助吗?

标签: c# asp.net


【解决方案1】:

Session_End 在会话结束时调用 - 通常在最后一次请求后 20 分钟(例如,如果浏览器处于非活动状态或关闭)。
由于没有请求,因此也没有响应。

如果没有活动会话,我建议在Application_AcquireRequestState 中进行重定向。请记住通过检查当前 url 来避免循环。

编辑:我不喜欢 .Nets 内置身份验证,示例位于 Global.asax

    protected void Application_AcquireRequestState(object sender, EventArgs e)
    {
        try
        {
            string lcReqPath = Request.Path.ToLower();

            // Session is not stable in AcquireRequestState - Use Current.Session instead.
            System.Web.SessionState.HttpSessionState curSession = HttpContext.Current.Session;

            // If we do not have a OK Logon (remember Session["LogonOK"] = null; on logout, and set to true on logon.)
            //  and we are not already on loginpage, redirect.

            // note: on missing pages curSession is null, Test this without 'curSession == null || ' and catch exception.
            if (lcReqPath != "/loginpage.aspx" &&
                (curSession == null || curSession["LogonOK"] == null))
            {
                // Redirect nicely
                Context.Server.ClearError();
                Context.Response.AddHeader("Location", "/LoginPage.aspx");
                Context.Response.TrySkipIisCustomErrors = true;
                Context.Response.StatusCode = (int) System.Net.HttpStatusCode.Redirect;
                // End now end the current request so we dont leak.
                Context.Response.Output.Close();
                Context.Response.End();
                return;
            }
        }
        catch (Exception)
        {

            // todo: handle exceptions nicely!
        }
    }

【讨论】:

  • 您能提供一个sn-p吗?我不是 asp.net 中的高级编码员。
  • @SKPaul 添加了示例,但是您应该正确测试并理解代码,并且在生产中使用之前完全理解它的后果!但这当然适用于任何解决方案。
  • 无需关闭浏览器(最终)触发 Session_End。用户只需在超时期间处于非活动状态(不发出请求)。这可能是因为浏览器关闭、用户离开、午休或忙于阅读(长?)页面 20 分钟。
  • @HansKesting 是的,当然,已编辑。这是一个说明不可能发出重定向的例子。
【解决方案2】:

如果您使用 FormsAuthentication 之类的东西来维护应用程序的安全性,那么这部分(您正在尝试做的部分)将为您完成。如果 FormsAuthentication 发现用户的会话已过期,它会将他或她重定向回您的登录页面。

其次,不要过分依赖Session_End,因为如果您将会话提供程序从 InProc 更改为 SQLServer,它将永远不会触发或其他进程外提供程序。

【讨论】:

  • 这个答案的措辞不正确。 FormsAuthentication 和 Session 是不同的东西。您可以拥有有效的表单身份验证票,但也可以拥有过期会话。也就是说,对于只提供到登录页面的重定向,您是正确的,表单身份验证将执行重定向。见:stackoverflow.com/questions/1470777/…
【解决方案3】:

您可以使用会话属性IsNewSession 来检测会话是否超时。

如果为此请求创建了新会话,则 ASP.NET HttpSessionState 类具有 IsNewSession() 方法,该方法返回 true。检测会话超时的关键是还要在请求中查找ASP.NET_SessionId cookie。

当然我也同意我们应该将下面的代码放在一些所谓的自定义 BasePage 中,所有页面都使用它,以有效地实现这一点。

override protected void OnInit(EventArgs e)
  {
       base.OnInit(e);   

if (Context.Session != null)
   {
if (Session.IsNewSession)
    {

     string CookieHeader = Request.Headers["Cookie"];
     if((CookieHeader!=null) && (CookieHeader.IndexOf("ASP.NET_SessionId") >= 0))
     {
      // redirect to any page you need to
      Response.Redirect("sessionTimeout.aspx");
     } 
   }
 }
}

如果您想将上述代码放在基页类中,请查看link 以获得更多说明。

【讨论】:

    【解决方案4】:

    您应该使用 Application_AcquireRequestState 您会发现 Application_AuthenticateRequest 不再有会话上下文(或从未有过)。 在我对此的研究中,我发现了这篇文章,它为我解决了这个问题。 感谢 Waqas Raja。

    asp.net: where to put code to redirect users without a session to the homepage?

    【讨论】:

      【解决方案5】:

      我认为您收到“响应在此上下文中不可用”,因为用户没有向服务器发出请求,因此您无法为其提供响应。请尝试使用 Server.Transfer。

      【讨论】:

      • 我也试过"Server.Transfer("~/NewPage.aspx", false);"。但不起作用。错误“对象引用未设置为对象的实例。”
      • 好吧,我想我会实现一个 javascript 计时器,设置为与会话超时相同的长度,然后使用 window.location 在超时时重定向它们。计时器会在页面重新加载时刷新,就像他们的会话一样。作为额外的奖励,您可以在用户的​​会话即将到期时警告用户。
      【解决方案6】:

      我觉得最简单的方法是使用元信息并让技巧发挥作用。考虑我们有一个页面WebPage.aspxWebPage.aspx.cs 文件中添加以下代码。

      private void Page_Load(object sender, System.EventArgs e){      
          Response.AddHeader("Refresh",Convert.ToString((Session.Timeout * 60) + 5));      
          if(Session[“IsUserValid”].ToString()==””)              
          Server.Transfer(“Relogin.aspx”);
      }
      

      在上面的代码中,一旦 Session 过期,WebPage.aspx 会在 5 秒后刷新。并在页面加载中验证会话,因为会话不再有效。该页面被重定向到重新登录页面。每次回发到服务器都会刷新会话,同样会在WebPage.aspx的元信息中更新。

      【讨论】:

        【解决方案7】:

        您可以在 web.config 中简单地执行以下操作

        <configuration>
        <system.web>
        <sessionState mode="InProc"  timeout="1" loginurl="destinationurl"/>
        </system.web>
        </configuration>
        

        因为,我们无法从 Session_End 重定向,因为那里没有响应/重定向。通过使用这个,当会话超时时,您将被重定向到 destinationurl。希望这会有所帮助。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-12-14
          • 1970-01-01
          • 1970-01-01
          • 2019-03-31
          • 2016-06-10
          • 2017-04-03
          相关资源
          最近更新 更多