HttpStatusCodeResult(401) возвращает 302 Found

Используя ASP.NET MVC 5, я хотел бы вернуть соответствующий код состояния HTTP для разных сценариев (401 для пользователя не аутентифицирован, 403, когда пользователь не имеет права на какой-либо ресурс и т. д.), чем обрабатывать их в jQuery.

Но проблема в том, что когда я пытаюсь вернуть 401, он всегда возвращает «302: найдено». В чем хитрость пользовательского кода состояния и почему это не работает?

public ActionResult My()
{
    if (User.Identity.IsAuthenticated == false)
    {
        return new HttpStatusCodeResult(401, "User is not authenticated."); 
            // Returns "302: Found"
    }

   // ... other code ...
}

EDIT 1: Интересный момент:

Если я заменю 401 на 404 следующим образом:

return new HttpNotFoundResult("User is not authenticated.");

Тогда он действительно дает 404, и jQuery может уловить проблему. Однако это не элегантное решение, так как код ошибки отличается.

EDIT 2: 302 мне не подходит, так как результат будет использоваться в jQuery.get().fail(), но 302 не вызовет fail()


person Adam Szabo    schedule 10.09.2013    source источник
comment
вы используете проверку подлинности с помощью форм?   -  person Daniel A. White    schedule 11.09.2013
comment
взгляните на это: stackoverflow.com/ вопросы/10348111/   -  person mrtig    schedule 11.09.2013
comment
mrtig: Я видел это раньше, но это не помогает, так как говорится, что это решается с помощью IIS Express. Я использую IIS Express, но у меня проблема.   -  person Adam Szabo    schedule 11.09.2013
comment
Дэниел А. Уайт: я использую встроенную аутентификацию по умолчанию в шаблоне ASP.NET MVC5 под названием «Индивидуальные учетные записи пользователей».   -  person Adam Szabo    schedule 11.09.2013


Ответы (1)


Лол, это ужасная проблема

Способ аутентификации в MVC заключается в том, что когда вы не вошли в систему и пытаетесь получить доступ к защищенной странице, возникает исключение 401. Затем MVC перехватывает это исключение и перенаправляет пользователя на страницу входа (это 302, которую вы видите)

Я полагаю, что есть несколько вещей, которые вы можете сделать, чтобы это исправить:

ИЗМЕНИТЬ

Согласно вашим комментариям, следующий код превратит все перенаправления в 401 при запросе через ajax. Это один из способов избежать перечисленных проблем

public class MvcApplication : HttpApplication {
    protected void Application_EndRequest() {
        var context = new HttpContextWrapper(Context);
        // If we're an ajax request, and doing a 302, then we actually need to do a 401
        if (Context.Response.StatusCode == 302 && context.Request.IsAjaxRequest()) {
            Context.Response.Clear();
            Context.Response.StatusCode = 401;
        }
    }
}
person Not loved    schedule 10.09.2013
comment
Редиректа не будет, так как метод контроллера вызывается через AJAX, поэтому мне нужно что-то отличное от 302, чтобы jQuery.get смог его распознать. - person Adam Szabo; 11.09.2013
comment
@user2270404 user2270404 взгляните на код Фила Хакса. Он создает модуль HTTP, чтобы решить эту проблему и в любом случае вернуть 401 (именно для случая ajax). Это немного беспорядочно, но это должно решить вашу проблему. Согласно статье, есть и лучший способ обойти это, если вы используете .NET 4.5. - person Not loved; 11.09.2013
comment
Я прочитал статью, она немного сумбурна. Я использую .NET 4.5.1 и проверил решение 4.5, но не нашел способа манипулировать свойством HttpResponse.SuppressFormsAuthenticationRedirect из моего метода, который возвращает ActionResult. Однако среди комментариев хака я нашел следующее: это довольно полезно с небольшим дополнением: gist.github.com/1264267 Если вы включите этот фрагмент кода, я буду рад принять ваш ответ. Еще раз спасибо. - person Adam Szabo; 11.09.2013
comment
@ user2270404 рад помочь :) - person Not loved; 11.09.2013
comment
Или вы знаете, где я могу установить HttpResponse.SuppressFormsAuthenticationRedirect? - person Adam Szabo; 11.09.2013
comment
@user2270404 user2270404 это просто Response.SuppressFormsAuthenticationRedirect = true, если вы ориентируетесь на .net 4.5 - person Not loved; 11.09.2013
comment
Спасибо. Однако SuppressFormsAuthenticationRedirect, похоже, не работает (по крайней мере, для AJAX) для меня, поэтому я буду придерживаться Application_EndRequest() - person Adam Szabo; 11.09.2013