redirect到endResponse为真的VS CompleteRequest和安全线程的页面
根据这些问题和答案 ,我想问一下什么是redirect的正确方法。
使用redirect(url,endResponse)的默认方式是抛出ThreadAbortException
因为调用endResponse=true
调用End()
方法,所以,如果你在try / catch块中使用它,这个exception显示在那里 ,被假定为错误,但实际上用户尝试通过停止其余的页面处理来redirect到页面。
其他可能的方式是通过HttpContext.Current.ApplicationInstance.CompleteRequest();
来调用Redirect(url, endResponse)
并使用endResponse=false
HttpContext.Current.ApplicationInstance.CompleteRequest();
通过使用你没有得到任何例外。
所以问题是什么是更好的使用和为什么。
为了解决redirect调用后输出页面内容的安全问题,不需要调用Response.Redirect
对于endResponse
为true
。 您可以通过另一种方式来完成这个任务,并避免同时产生一个ThreadAbortExceptionexception( 这总是不好的 )。 下面是我用5个button创build的页面的片段,这些button以不同的方式导致redirect, RedirectRenderOverride
button是理想的,因为它是触发Render方法什么也不做的。 已经使用NoRedirect加载项进行了testing。 只有两种情况避免输出除302对象移动响应之外的任何内容 – RedirectEnd
和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
, 根据Eric Lippert的说法 , Thread.Abort
,“最好表示devise不好,可能不可靠,而且非常危险。
您必须始终使用endRespose=true
来调用redirect,否则任何黑客都可以通过简单地保持redirect来查看页面上的内容。
为了certificate我使用Firefox的NoRedirect插件来保存redirect。 然后我testing两个案例,这里是结果:
我有一个简单的页面,其中的文字
<form id="form1" runat="server"> <div> I am making a redirect - you must NOT see this text. </div> </form>
然后在页面加载尝试使两种情况下的redirect:
第一种情况,使用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,并停止其他处理是由 – 从函数返回,而不是继续。
例如,如果你检查用户是否被authentication,他可以看到该页面,如果不是,他必须redirect到login,甚至在login,如果你尝试redirect他endResponse为false,然后持有redirect黑客可以看到 – 什么你相信不能因为你使用redirect。
我的基本点在于如果您不停止将数据发送回浏览器,则显示存在的安全线程。 redirect是给浏览器的头文件和指令,但同时你需要停止发送其他数据,你必须停止发送你的页面的任何其他部分。