Перенаправить на страницу с помощью endResponse в true VS CompleteRequest и поток безопасности
Основы на эти вопросы и ответы там, мне нравится спрашивать, что является правильным способом перенаправления.
По умолчанию с помощью Redirect (url, endResponse) вызывается ThreadAbortException
, потому что вызывается с endResponse=true
, который вызывает End()
, и поэтому, если вы используете его внутри блока try/catch, это исключение показано там, и это можно считать ошибкой, но на самом деле пользователь пытается перенаправить на страницу, остановив оставшуюся часть обработки страницы.
Другими возможными способами является вызов Redirect(url, endResponse)
с endResponse=false
, следующий за HttpContext.Current.ApplicationInstance.CompleteRequest();
. Используя это, вы не получите никаких исключений.
Итак, вопрос в том, что лучше использовать и почему.
Ответы
Ответ 1
Вы всегда должны перенаправлять перенаправление с помощью endRespose=true
, иначе любой хакер может увидеть, что на странице, просто удерживая перенаправление.
Чтобы доказать, что я использую плагин NoRedirect для Firefox, чтобы провести перенаправление. Затем я проверяю два случая, и вот результаты:
У меня есть простая страница с текстом внутри нее
<form id="form1" runat="server">
<div>
I am making a redirect - you must NOT see this text.
</div>
</form>
а затем на загрузке страницы попробуйте сделать перенаправление с обоими случаями:
Первый случай, используя полный запрос();
try
{
// redirect with false that did not throw exception
Response.Redirect("SecondEndPage.aspx", false);
// complete the Request
HttpContext.Current.ApplicationInstance.CompleteRequest();
}
catch (Exception x)
{
}
и там бум, вы можете видеть, что внутри страницы!
![4ku7X.gif]()
И второй случай
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)
{
}
Ничего не показано сейчас.
![Ko6vz.gif]()
Итак, если вам не нравится, когда хакер видит, что на вашей странице, , вы должны вызывать его с помощью endResponse на true и останавливать выполнение другой обработки -eg return from function и не продолжать.
Если, например, вы проверяете, аутентифицирован ли пользователь, он может видеть эту страницу, или если он не должен перенаправляться на вход в систему, и даже при входе в систему, если вы попытаетесь перенаправить его с помощью endResponse на false, тогда проведение перенаправления хакера может см. то, что вы считаете невозможным, потому что вы используете перенаправление.
Моя основная точка заключается в том, чтобы показать защищенный поток, который существует, если вы не перестаете отправлять данные обратно в браузер. Переадресация - это заголовок и инструкция для браузера, но в то же время вам необходимо прекратить отправку любых других данных, вы должны прекратить отправку любой другой части своей страницы.
Ответ 2
Не требуется вызывать Response.Redirect
с true
для endResponse
для решения проблемы безопасности вывода содержимого страницы после вызова переадресации. Вы можете сделать это другим способом и избегать одновременного исключения ThreadAbortException (который всегда плох). Ниже приведены фрагменты страницы, которую я создал с 5 кнопками, которые вызывают переадресацию по-разному, причем кнопка RedirectRenderOverride
является идеальной, так как она запускает метод Render, чтобы ничего не делать. Это было протестировано с надстройкой NoRedirect. Только два случая исключают вывод чего-либо, кроме ответа на перемещение объекта 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
внутренне и согласно Эрику Липперту, называя Thread.Abort
, "в лучшем случае свидетельствует о плохом дизайне, возможно, ненадежном и чрезвычайно опасно".