Перенаправить на страницу с помощью 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, "в лучшем случае свидетельствует о плохом дизайне, возможно, ненадежном и чрезвычайно опасно".