6

基于这个问题和那里的答案,我想问什么是正确的重定向方式。

使用Redirect(url, endResponse)的默认方法是 throwThreadAbortException调用方法endResponse=trueEnd()因此,如果您在 try/catch 块中使用它,则会在此处显示此异常并且可以假定为错误,但实际上用户试图通过停止页面处理的其余部分来重定向到页面。

其他可能的方法是通过使用以下方式调用Redirect(url, endResponse)endResponse=falseHttpContext.Current.ApplicationInstance.CompleteRequest();不会得到任何异常。

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

4

2 回答 2

5

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

为了证明我使用 Firefox 的NoRedirect插件来保存重定向。然后我测试了这两种情况,结果如下:

我有一个简单的页面,里面有那个文本

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

然后在页面加载时尝试使用两种情况进行重定向:

第一种情况,使用 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 为 true并停止其他处理 - 例如从函数返回而不继续。

例如,如果您检查用户是否经过身份验证,他可以看到该页面,或者如果没有,他必须重定向到登录,甚至在登录时,如果您尝试使用 endResponse 将他重定向为 false,那么保持重定向黑客可以看到 - 什么你相信不能因为你使用了Redirect。

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

于 2013-02-01T06:49:36.347 回答
4

无需调用for即可Response.Redirect解决重定向调用后输出页面内容的安全问题。您可以通过另一种方式完成此操作,并避免同时导致 ThreadAbortException (这总是不好的)。下面是我使用 5 个按钮创建的页面片段,这些按钮以不同的方式导致重定向,该按钮是理想的,因为它会触发 Render 方法不执行任何操作。这已使用 NoRedirect 加载项进行了测试。只有两种情况避免输出除 302 对象移动响应之外的任何内容 -和.trueendResponseRedirectRenderOverrideRedirectEndRedirectRenderOverride

代码在前面

<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根据 Eric Lippert的说法,调用Thread.Abort“充其量是糟糕设计的表现,可能不可靠,而且极其危险。”

于 2013-02-01T07:00:22.813 回答