重定向到endResponse为真的VS CompleteRequest和安全线程的页面

时间:2013-02-01 06:49:36

标签: asp.net security redirect

基于this questions and the answers there,我想问一下重定向的正确方法是什么。

使用Redirect(url, endResponse)的默认方式是抛出ThreadAbortException因为调用endResponse=true方法调用End()因此,如果您在try /中使用它catch块,这个exception shown there,可以假设为错误,但实际上用户试图通过停止页面处理的其余部分来重定向到页面。

其他可能的方法是Redirect(url, endResponse)endResponse=falseHttpContext.Current.ApplicationInstance.CompleteRequest();跟随{{1}}使用它,不会有任何例外情况。

所以问题是什么更好用,为什么。

2 个答案:

答案 0 :(得分:5)

您必须始终使用endRespose=true调用重定向,否则任何黑客都可以通过简单地保留重定向来查看页面上的内容。

要证明我使用Firefox的NoRedirect插件来保存重定向。然后我测试了两个案例,结果如下:

我有一个包含该文字的简单页面

<form id="form1" runat="server">
<div>
I am making a redirect - you must NOT see this text.
</div>
</form>

然后在Page load上尝试使用两种情况进行重定向:

第一种情况,使用Complete Request();

    try
    {
        // redirect with false that did not throw exception
        Response.Redirect("SecondEndPage.aspx", false);
        // complete the Request
        HttpContext.Current.ApplicationInstance.CompleteRequest();
    }
    catch (Exception x)
    {

    }
繁荣,你可以在页面内看到什么!

第二种情况

try
{
    // this is throw the ThreadAbortException exception
    Response.Redirect("SecondEndPage.aspx", true);
}
catch (ThreadAbortException)
{
    // ignore it because we know that come from the redirect
}
catch (Exception x)
{

}

现在没有显示。

因此,如果你不喜欢黑客在你的页面上看到什么,你必须使用endResponse将其调用为真并停止进行其他处理 - 例如从函数返回而不是继续。< / p>

例如,如果您检查用户是否已通过身份验证,他可以看到该页面,或者如果不是,则必须重定向到登录,如果您尝试将endResponse重定向为false,则甚至在登录中,然后持有重定向黑客可以看 - 你认为不能因为你使用重定向。

我的基本观点这里是显示存在的安全线程,如果您没有停止将数据发送回浏览器。重定向是浏览器的标题和说明,但同时您需要停止发送任何其他数据,您必须停止发送页面的任何其他部分。

答案 1 :(得分:3)

Response.Redirect true endResponse调用RedirectRenderOverride来解决重定向调用后输出页面内容的安全问题。您可以通过另一种方式完成此操作,并避免同时导致ThreadAbortException(which is always bad)。下面是我使用5个按钮创建的页面的片段,这些按钮以不同的方式导致重定向,RedirectEnd按钮是理想的,因为它是触发Render方法无效的按钮。这已使用NoRedirect加载项进行了测试。只有两种情况可以避免输出302对象移动响应以外的任何内容 - RedirectRenderOverride<asp:Button ID="Button1" runat="server" OnClick="RedirectCompleteRequest" Text="RedirectCompleteRequest"/> <asp:Button ID="Button2" runat="server" OnClick="RedirectClear" Text="RedirectClear"/> <asp:Button ID="Button3" runat="server" OnClick="RedirectRenderOverride" Text="RedirectRenderOverride"/> <asp:Button ID="Button4" runat="server" OnClick="RedirectEnd" Text="RedirectEnd"/> <asp:Button ID="Button5" runat="server" OnClick="RedirectEndInTryCatch" Text="RedirectEndInTryCatch"/>

前面的代码

public partial class _Default : Page {
    private bool _isTerminating;

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

    protected void RedirectCompleteRequest(object sender, EventArgs e)
    {
        Response.Redirect("Redirected.aspx", false);
        HttpContext.Current.ApplicationInstance.CompleteRequest();
    }

    protected void RedirectClear(object sender, EventArgs e)
    {
        Response.Clear();
        Response.Redirect("Redirected.aspx", false);
    }

    protected void RedirectRenderOverride(object sender, EventArgs e)
    {
        Response.Redirect("Redirected.aspx", false);
        _isTerminating = true;
    }

    protected void RedirectEndInTryCatch(object sender, EventArgs e)
    {
        try {
            Response.Redirect("Redirected.aspx");
        } catch (ThreadAbortException) {
            // eat it
        } finally {
            Response.Write("Still doing stuff!");
        }
    }

    protected override void RaisePostBackEvent(IPostBackEventHandler sourceControl, string eventArgument)
    {
        if (!_isTerminating) {
            base.RaisePostBackEvent(sourceControl, eventArgument);
        }
    }

    protected override void Render(HtmlTextWriter writer)
    {
        if (!_isTerminating) {
            base.Render(writer);
        }
    }
}

代码背后

Response.End

Thread.CurrentThread.Abort在内部调用Thread.Abortaccording to Eric Lippert调用{{1}},&#34;充其量表示设计不当,可能不可靠,极其危险。 #34;