基于this questions and the answers there,我想问一下重定向的正确方法是什么。
使用Redirect(url, endResponse)的默认方式是抛出ThreadAbortException
因为调用endResponse=true
方法调用End()
因此,如果您在try /中使用它catch块,这个exception shown there,可以假设为错误,但实际上用户试图通过停止页面处理的其余部分来重定向到页面。
其他可能的方法是Redirect(url, endResponse)
跟endResponse=false
跟HttpContext.Current.ApplicationInstance.CompleteRequest();
跟随{{1}}使用它,不会有任何例外情况。
所以问题是什么更好用,为什么。
答案 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.Abort
,according to Eric Lippert调用{{1}},&#34;充其量表示设计不当,可能不可靠,极其危险。 #34;