Weird AJAX перенаправляет проблему 401 с IIS

Удалить этот вопрос? Я понял, в чем проблема, и это не было ИИС... См. Мой ответ ниже для результата.

Оригинальный вопрос Я работаю над ASP.Net MVC-приложением и забегаю к странной проблеме с перенаправлением URL-адресов Rewrite и AJAX.

Я добавил следующее правило перезаписи для моего Web.config в корневом сайте.

<rewrite>
    <rules>
        <rule name="Account" stopProcessing="true">
            <match url="^SubApp/Account/(.*)$" />
            <action type="Redirect" url="Account/{R:1}" redirectType="Found" />
        </rule>
    </rules>
</rewrite>

Кажется, что все работает нормально, если я использую Permanent или Temporary redirectType в конфигурации, но с ошибкой с страницей ошибок HTTP Error 401.0 - Unauthorized IIS.

Когда я делаю обычный запрос GET через браузер для действия, которое запускает это правило, например. https://some-site/SubApp/Account/Settings, тогда я получаю 302 Найдено, и заголовок местоположения установлен на ожидаемый URL https://some-site/Account/Settings, и соответствующая страница отображается.

Однако, когда я делаю запрос GET через JQuery AJAX, т.е. $.get('https://some-site/SubApp/Account/Settings'), возвращаемый код состояния ответа 401 Unauthorized, но у него все еще есть соответствующий заголовок местоположения.

Содержимое ответа представляет собой стандартную страницу ошибки IIS HTTP Error 401.0 - Unauthorized.

Похоже, что все работает нормально, если я использую типы перенаправления Permanent или Temporary в конфигурации, но не работает только с Found.

/SubApp - отдельное приложение, которое находится ниже корневого сайта в /.

Что происходит?

Скриншоты

redirectType="Permanent" Permanent Redirect

redirectType="Found" Found Redirect

redirectType="Temporary" Temporary Redirect

Как видно из скриншотов, единственное отличие - это redirectType, указанный в Web.config.

Как вы можете видеть, переадресации происходят, как ожидалось, с исключением типа перенаправления Found, который я ожидал бы получить перенаправление ответа 302 - Found на тот же URL, что и другие.

Ответы

Ответ 1

Ahhhh, вы знаете, когда вы не думаете о чем-то какое-то время, и вас поражают внезапным вдохновением... Ну, это случилось прошлой ночью, и я обнаружил, что этот маленький самородок встал на место, чтобы "исправить" сопротивление MVC при перенаправлении AJAX запрашивает, когда аутентификация завершается неудачно...

protected void Application_EndRequest()
{
    var context = new HttpContextWrapper(Context);
    // MVC retuns a 302 for unauthorized ajax requests so alter to request status to be a 401
    if (context.Response.StatusCode == 302 && context.Request.IsAjaxRequest() && !context.Request.IsAuthenticated)
    {   
        context.Response.Clear();
        context.Response.StatusCode = 401;
    }
}

И, неудивительно, context.Request.IsAuthenticated всегда false, поскольку, как представляется, он получает reset путем перенаправления.

Обновлено, с небольшой помощью блога Бранислава Абаджимаринова по этому вопросу.

protected void Application_EndRequest()
{
    var context = new HttpContextWrapper(Context);
    // MVC returns a 302 for unauthorized ajax requests so alter to request status to be a 401

    if (context.Response.StatusCode == 302 && context.Request.IsAjaxRequest())
    {
        //Unfortunately the redirect also clears the results of any authentication
        //Try to manually authenticate the user...
        var authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
        if (authCookie != null)
        {
            var authTicket = FormsAuthentication.Decrypt(authCookie.Value);
            if (authTicket != null && !authTicket.Expired)
            {
                var roles = authTicket.UserData.Split(',');
                HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(new FormsIdentity(authTicket), roles);
            }
        }

        if (!context.Request.IsAuthenticated)
        {
            context.Response.Clear();
            context.Response.StatusCode = 401;
        }

    }
}

И все работает как ожидалось.

Вопрос только в том, должен ли я удалить этот вопрос?