如何在ASP.NET中处理表单身份验证超时异常?

10
如果会话已过期并且用户单击链接到另一个 Web 表单,asp.net 认证会自动将用户重定向到登录页面。
然而,有些情况下用户不会单击其他 Web 表单的链接。例如:在 gridviews 中使用编辑链接、在文本框中使用 AutoCompleteExtender 并尝试获取信息的应用程序以及基本上每次执行 postback 且事件未被 asp.net 认证自动处理时。
如何处理这些异常情况是最好的方式?
更新:我刚刚修改了问题标题:表单身份验证超时,而不是最初的会话超时。感谢让我意识到这种区别。
更新:我刚刚创建了一个新问题,其中包含我面临的具体问题:如何使用 UpdatePanel 处理由于已过期的身份验证票据而引起的异常?。令人惊讶的是,我没有找到太多相关信息。我非常感谢您的帮助。

1
不是因为asp.net身份验证未处理请求,而是Ajax的XmlHttpRequest将非XML响应返回给浏览器。问题实际上出现在浏览器端,您应该在那里找到有关您问题的答案。 - Wiktor Zychla
当会话超时并且用户在GridView中单击编辑链接时,您希望发生什么? - James Johnson
嗨@詹姆斯。如果会话已过期,我想将用户带到登录页面。因此,如果单击编辑链接(或生成任何其他后台请求),我应该处理生成的异常并将用户带到登录页面。到目前为止,我想到的唯一解决方案是在处理后台请求的每个方法中添加try-catch,但我相信肯定有更好的方法来解决这个问题。 - aleafonso
@aleafonso 只是好奇为什么您在几个月后取消了接受? - Adam Tuliper
@AdamTuliper请看下面您的回答下面的评论。它描述了情况。我仍然遇到同样的问题。 - aleafonso
@aleafonso请看下面我的回复。 - Adam Tuliper
3个回答

10
这就是为什么许多系统在页面上包含计时器来给出大致的超时时间。这对于交互式页面来说是很困难的。你真的需要钩取ajax函数并查看返回状态码,这有点困难。 另一种选择是使用以下基于代码的方法,在页面生命周期早期运行并执行ajax重定向到登录页面。否则,你将被困在试图拦截来自ajax的返回代码中,并且在asp.net中,ajax是“为你”完成的(即不像jQuery那样更加手动化),你会失去这种检测的便利性。

http://www.eggheadcafe.com/tutorials/aspnet/7262426f-3c65-4c90-b49c-106470f1d22a/build-an-aspnet-session-timeout-redirect-control.aspx

如果要快速解决问题,您可以直接在pre_init中尝试它 http://forums.asp.net/t/1193501.aspx

编辑 需要的是表单身份验证超时,而不是会话超时。表单身份验证超时的操作比会话超时的操作更为复杂。每个请求都会更新会话超时时间。表单身份验证票据只有在过去了一半的时间后才会实际更新。因此,如果您将超时设置为1小时并在其中发送一个请求25分钟,则会话将重置为1小时超时,表单身份验证票证不会被触及,并在35分钟后过期!为了解决这个问题,请同步会话超时和表单身份验证票证。这样,您仍然可以检查会话超时。如果您不喜欢这种方法,那么还是按照下面的方法同步超时时间,然后解析认证票证并读取其超时时间。您可以使用FormsAuthentication.Decrypt来做到这一点-请参见:

从asp.net代码后台读取表单身份验证cookie

请注意,此代码要求在登录时设置一些会话值-在本例中为"UniqueUserId"。还要更改下面的登录页路径以适应您的路径。

protected void Application_PreRequestHandlerExecute(object sender, EventArgs e) { //仅在会话状态可用时访问会话状态 if (Context.Handler is IRequiresSessionState || Context.Handler is IReadOnlySessionState) { //如果我们已经通过身份验证并且此处没有会话,则重定向到登录页面。 HttpCookie authenticationCookie = Request.Cookies[FormsAuthentication.FormsCookieName]; if (authenticationCookie != null) { FormsAuthenticationTicket authenticationTicket = FormsAuthentication.Decrypt(authenticationCookie.Value); if (!authenticationTicket.Expired) { if (Session["UniqueUserId"] == null) { //这意味着出现某些原因,认证票据过期之前会话已过期。强制重新登录。 FormsAuthentication.SignOut(); Response.Redirect("Login.aspx", true); return; } } } } }

嗨,亚当。我刚刚尝试了这个解决方案。但是,如果票已过期并且我在GridView中的“Edit”链接上单击(在UpdatePanel中),则事件不会被“Application_PreRequestHandlerExecute”处理,因为它在到达那里之前就中断了(我猜)。我知道错误与票证过期有关,因为当票证未过期时,它不会中断。欢迎任何其他想法! - aleafonso
你是说当票证过期时,PreRequestHandlerExecute 永远不会执行? - Adam Tuliper
Response.Redirect对于ajax调用无效。您需要检测ajax调用并进行特殊处理,例如返回409并添加一个包含要重定向到的URL的X-Redirect头。在JavaScript端使用jQuery,设置全局错误处理程序并处理409特殊情况,以便将其重定向到X-Redirect头的内容。 - Softlion
1
@Softion 当然没问题,但这篇帖子没有标记为MVC,而是针对Web Forms的。 - Adam Tuliper
@AdamTuliper 我正在使用Web表单!当然,我使用jQuery(大多数情况下是jQuery-ui)。我不太确定这是否是我出现错误的原因,因为它可能发生在我单击GridView中的链接时,而且根本没有涉及jQuery。 - aleafonso
显示剩余8条评论

1

如果您正在使用表单身份验证,当表单身份验证票证过期时,用户将被重定向到登录页面,这与会话过期不同。

如果适当的话,您可以考虑增加表单身份验证超时时间。甚至可以使用持久性cookie。但是,如果它过期了,没有真正的替代方案可以重定向到登录页面 - 其他任何操作都会不安全。

处理会话超时的一种方法是将会话用作缓存,并将任何重要内容保留到后备存储(例如数据库)。然后在访问会话中的任何内容之前进行检查,并在必要时刷新:

MyType MyObject
{
    get
    {
        MyType myObject = Session["MySessionKey"] as MyType
        if (myObject == null)
        {
            myObject = ... get data from a backing store
            Session["MySessionKey"] = myObject;  
        }
        return myObject;
    }
    set
    {
        Session["MySessionKey"] = value;
        ... and persist it to backing store if appropriate
    }
}

嗨,乔。我确实正在使用表单身份验证,我刚刚更新了问题。在登录期间,如果用户想要被记住,我会创建一个持久性cookie,否则,我只会创建身份验证“票证”。如果身份验证票证已过期并且用户请求另一个Web表单,则会重定向到登录页面(这是可以的)。我的问题出现在用户等待太长时间以执行任何涉及回发的事件(除了页面请求)并且票证已经过期的情况下。在这种情况下我该怎么办?非常感谢您的时间。 - aleafonso

0
如果您正在使用主页面或基础页面,我建议在页面生命周期的某个事件中添加一些逻辑来检查会话是否为新会话:
protected void Page_Load(object sender, EventArgs e)
{
    if (Session.IsNewSession)
    {
        //do whatever you need to do
    }
}

1
我相信他所说的“会话超时”实际上是指“身份验证会话超时”,例如表单 cookie 的超时。而你的建议对于检测身份验证不再有效并不是很有帮助。 - Wiktor Zychla
这正是我想表达的。感谢 @Wiktor 澄清。对于误解,抱歉 James。 - aleafonso
将表单身份验证逻辑添加到主页面代码中的问题在于,此逻辑在内容页面代码之后执行。 - JohnH

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