在Session_end事件中重定向到另一个页面

13

当会话超时时,我希望能够自动重定向到登录页面。

在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。

在此上下文中无法使用响应。

有什么线索可以解决这个问题吗?


2
你应该在认证元素中完成这个操作,而不是在代码中。 - Simon Whitehead
1
当您说会话超时后重定向到登录页面时,是否意味着您希望浏览器(客户端)自动从服务器事件触发重定向?如果是这样,那么这将需要更多的内容,比如使用SignalR中心来触发客户端JavaScript重定向,而不仅仅是服务器代码。 - SteveChapman
3
据我所知,Session_End事件不会作为请求的一部分被触发。当超时发生时,它会在后台触发。下次用户回来时,他会自动获得一个新的会话,因为旧的会话已经超时了。所以当Session_End事件发生时,没有当前可被重定向的Response - user1429080
这个相关问题可能会有帮助? - SteveChapman
7个回答

10

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

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

编辑:我不喜欢.Net内置的身份验证,示例放在中:

    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!
        }
    }

请提供一小段代码吗?我不是asp.net的高级编程人员。 - s.k.paul
@SKPaul 添加了示例,但在生产环境中使用之前,您应该充分测试并完全理解代码及其后果!当然,这适用于任何解决方案。 - NiKiZe
不需要关闭浏览器来(最终)触发Session_End。用户只需在超时期间处于非活动状态(不发出请求)。这可能是因为浏览器已关闭,用户导航离开,他休息吃午饭或忙于阅读长页面20分钟。 - Hans Kesting
@HansKesting 当然,已编辑。这是一个例子,以澄清无法发出重定向的情况。 - NiKiZe

4
如果你正在使用像FormsAuthentication这样的工具来维护应用程序的安全性,那么你所尝试做的部分就已经完成了。如果FormsAuthentication发现用户的会话已过期,它会将其重定向回登录页面。
其次,不要过于依赖Session_End,因为如果你从InProc更改到SQLServer或其他进程外提供程序,它将永远不会触发

这个答案表述不正确。FormsAuthentication和Session是两个不同的东西。你可以拥有一个有效的forms auth ticket,但也可能有一个即将过期的session。话虽如此,就提供的仅仅是重定向到登录页面而言,你是正确的,forms authentication会进行重定向。参见:https://dev59.com/N3M_5IYBdhLWcg3wPAZF - b_levitt

1
您可以使用会话属性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");
     } 
   }
 }
}

如果您想将上述代码放入基础页面类中,请查看此链接以获得更多解释。


1

0

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


我也尝试了 "Server.Transfer("~/NewPage.aspx", false);"。但是不起作用。错误信息为 "对象引用未设置到对象的实例。"。 - s.k.paul
好的,我想我会实现一个JavaScript计时器,设置为与您的会话超时时间相同,然后使用window.location在超时时将其重定向。计时器会在页面重新加载时刷新,就像他们的会话一样。作为额外的奖励,您可以在用户的会话即将过期时警告用户。 - Zerkey

0
我认为最简单的方法是使用元信息并使技巧起作用。考虑我们有一个页面WebPage.aspx,在WebPage.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”);
}

在上述代码中,一旦会话过期,WebPage.aspx 将在 5 秒后刷新。在页面加载时,会验证会话是否有效,如果会话无效,则将页面重定向到重新登录页面。每次向服务器提交后,都会刷新会话,并将其更新到 WebPage.aspx 的元信息中。

-1

你可以在 web.config 文件中简单地执行以下操作

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

由于在Session_End中没有响应/重定向,因此我们无法进行重定向。通过使用此方法,当会话超时时,您将被重定向到目标URL。希望这可以帮助您。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接