【问题标题】:When is it safe to do a Response.Redirect() without throwing an exception?什么时候可以安全地执行 Response.Redirect() 而不会引发异常?
【发布时间】:2010-03-29 17:27:42
【问题描述】:

我有一个为我所有需要身份验证的页面扩展 System.Web.UI.Page 的中间类。该类主要进行自定义身份验证处理。

当访问权限不足的用户尝试访问页面时,我会尝试将用户重定向回登录页面,同时防止执行任何进一步的页面事件(即 Page_load)。想到的第一个解决方案是 Response.Redirect 的默认实现。当然,这样做的缺点是可能会抛出 ThreadAbortExceptions。

所以我的问题是:在页面生命周期中何时(如果有的话)执行 Response.Redirect() 而不抛出 ThreadAbortException 实际上是安全的吗?

public class CustomPage : System.Web.UI.Page
{
    protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);
        if (!IsValid())
            Response.Redirect("login.aspx", true);
    }
}

【问题讨论】:

  • 为什么不希望抛出 ThreadAbortException。它被抛出以停止对请求页面的任何处理。
  • 我猜这是真的。但是,如果您在 VS 中打开自动异常中断,Response.Redirect() 并不总是抛出异常,但它仍然会跳过处理页面的其余部分。

标签: c# asp.net response.redirect


【解决方案1】:

如果您将 true 作为第二个参数传递,它永远不会“安全”——它总是会抛出异常。在内部,Response.Redirect() 调用Response.End(),直接中止当前线程。

在不引发异常的情况下截断HttpRequest 的唯一“安全”方法是使用HttpApplication.CompleteRequest(),但这会导致在当前请求中进一步执行代码。

【讨论】:

  • 我不确定情况是否如此。我不这么认为的原因是因为 Response.End() 在抛出异常之前检查 IsInCancellablePeriod 。因此,不知何故,可以在不遇到该异常的情况下调用 Response.End()。
  • 您需要深入挖掘。您将看到 IsInCancellablePeriod 完全由 HttpApplication.IExecutionStep 接口对象上的标志控制。对于任何 CallHandler 实现(调用 ProcessRequest,它调用页面生命周期),此标志定义为 return !(this._application.Context.Handler is IHttpAsyncHandler);。换句话说,除非你正在执行一个异步请求,否则它在整个页面生命周期内始终为 false。
  • 所以如果我在没有 try/catch 的情况下调用 Response.Redirect("login.aspx") 不应该命中 HttpApplication.Application_Error (它不是)?
  • 我认为应该如此,尽管我可能是错的。 ThreadAbortException 是一个非常特殊的异常。
【解决方案2】:

很好奇,你为什么要自己做这个?如果有的话,您应该使用身份验证提供程序之一(最终,可以自定义 FormsAuthentication 以处理您能想到的几乎任何场景)。

然后,您可以在 web.config 文件中使用 authorization element 来指示匿名用户无法访问哪些页面/目录。 ASP.NET 将负责其余的工作,将用户重定向到您指定的登录页面,并在用户登录后重定向回来。

【讨论】:

  • 这是我考虑过的一种选择。我认为这是我想出的解决方案中最简单、最容易维护的。所有需要身份验证的页面都保存在一个目录中。访问页面的角色有 5 个以上,目录中的每个页面 (20+) 有不同的角色要求。我看到自己在 web.config 中为每个需要身份验证的页面创建了一个位置部分。我的另一个选择是将文件拆分到每个角色的单独目录中。如果用户担任多个角色,我遇到的问题是路径维护。
【解决方案3】:

如果您不想要 ThreadAbort 异常,您应该将 False 传递给 endResponse 参数。当然,这意味着您必须处理页面的其余部分,这很难做到。

除非您正在做一些非常愚蠢的事情,例如持有锁,否则在 ASP.NET 页面中引发 ThreadAbort 异常是完全安全的。

另一种选择是使用 Server.Transfer。这比重定向具有更好的性能,但它也使用 ThreadAbort 异常。

【讨论】:

    猜你喜欢
    • 2014-05-29
    • 1970-01-01
    • 1970-01-01
    • 2015-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多