Код ответа 401 для запросов json с ASP.NET MVC

Как отключить стандартную обработку кода ответа 401 в ASP.NET (перенаправление на страницу входа) для запросов AJAX / JSON?

Для веб-страниц это нормально, но для AJAX мне нужно получить правильный код ошибки 401 вместо красивого 302/200 для страницы входа.

Обновлять: Есть несколько решений от Фила Хаака, премьер-министра ASP.NET MVC - http://haacked.com/archive/2011/10/04/prevent-forms-authentication-login-page-redirect-when-you-donrsquot-want.aspx

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
35
0
20 996
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Вы можете создать собственный FilterAttribute, реализующий интерфейс IAuthorizationFilter.

В этом атрибуте вы добавляете логику, чтобы определить, должен ли запрос возвращать JSON. Если это так, вы можете вернуть пустой результат JSON (или сделать что угодно), если пользователь не вошел в систему. Для других ответов вы просто перенаправляете пользователя, как всегда.

Более того, вы можете просто переопределить OnAuthorization класса AuthorizeAttribute, чтобы вам не пришлось изобретать велосипед. Добавьте логику, о которой я упоминал выше, и перехватите, если filterContext.Cancel истинно (filterContext.Result будет установлен в экземпляр класса HttpUnauthorizedResult.

Узнайте больше о «Фильтры в ASP.NET MVC CodePlex Preview 4» в блоге Фила Хакса. Это также относится к последнему превью.

Но я все еще не могу получить код состояния ответа 401 для запроса AJAX. Даже если я настроил ответ в фильтре авторизации. Поскольку инфраструктура ASP.NET, которая перехватывает ответ 401 и перенаправляет на страницу входа, находится поверх ASP.NET MVC. Сообщать, что пользователь не вошел в журнал по пустому результату JSON, не очень правильно ...

derigel 24.09.2008 19:04

До сих пор я не совсем понимал, что вы имели в виду. Я добавляю новый ответ, который решит вашу проблему.

Troels Thomsen 25.09.2008 02:24
Ответ принят как подходящий

Среда выполнения ASP.NET разработана таким образом, что она всегда перенаправляет пользователя, если для HttpResponse.StatusCode установлено значение 401, но только при обнаружении раздела <authentication /> файла Web.config.

Удаление раздела аутентификации потребует от вас реализации перенаправления на страницу входа в свой атрибут, но это не должно иметь большого значения.

Лучший способ реализовать собственное перенаправление - создать подкласс AuthorizeAttribute, а при отсутствии авторизации установить результат в RedirectResult вместо HttpUnauthorizedResult.

Joseph Daigle 07.01.2010 18:44

Да, но в этом случае OP хотел бы отправить HTTP-код 401, но не перенаправлять (для правильной работы с JSON).

Troels Thomsen 08.01.2010 23:34

У меня работает - хотя я настроил параметр как <authentication mode = "None" /> вместо того, чтобы полностью удалять атрибут.

Timothy Lee Russell 15.06.2013 07:20

Гм - за исключением того, что я использую проверку подлинности с помощью форм в контроллерах MVC, так что на самом деле это не работает для меня. Требуется решение для аутентификации 404 && Forms, а не либо ||.

Timothy Lee Russell 18.06.2013 08:18

Что делать, если вы хотите использовать аутентификацию с помощью форм и настроить перенаправление 401?

DevDave 29.08.2013 20:59

@DevDave - Смотри мой ответ.

Timothy Lee Russell 30.08.2013 02:52

Вы также можете использовать Global.asax, чтобы прервать этот процесс примерно так:

    protected void Application_PreSendRequestHeaders(object sender, EventArgs e) {
        if (Response.StatusCode == 401) {
            Response.Clear();
            Response.Redirect(Response.ApplyAppPathModifier("~/Login.aspx"));
            return;
        }
    }

Я сделал это, за исключением того, что проверил 302 и X-Requested-With в ответе от @troethom выше.

Marc 09.09.2010 22:35

В классическом ASP.NET вы получаете код ответа HTTP 401 при вызове WebMethod с помощью Ajax. Я надеюсь, что они изменят его в будущих версиях ASP.NET MVC. Прямо сейчас я использую этот хак:

protected void Application_EndRequest()
{
    if (Context.Response.StatusCode == 302 && Context.Request.Headers["X-Requested-With"] == "XMLHttpRequest")
    {
        Context.Response.Clear();
        Context.Response.StatusCode = 401;
    }
}

Это действительно хорошее временное решение, если вам нужно что-то быстро работающее. В противном случае я бы попытался реализовать ответ @troethom.

Joseph Daigle 07.01.2010 18:44

Мне нужна была проверка подлинности с помощью форм и возвращение 401 для запросов Ajax, которые не прошли проверку подлинности.

В конце концов, я создал настраиваемый атрибут AuthorizeAttribute и украсил методы контроллера. (Это в .Net 4.5)

//web.config

<authentication mode = "Forms">
</authentication>

// контроллер

[Authorize(Roles = "Administrator,User"), Response302to401]
[AcceptVerbs("Get")]
public async Task<JsonResult> GetDocuments()
{
    string requestUri = User.Identity.Name.ToLower() + "/document";
    RequestKeyHttpClient<IEnumerable<DocumentModel>, string> client =
        new RequestKeyHttpClient<IEnumerable<DocumentModel>, string>(requestUri);

    var documents = await client.GetManyAsync<IEnumerable<DocumentModel>>();

    return Json(documents, JsonRequestBehavior.AllowGet);
}

// authorizeAttribute

public class Response302to401 : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            if (filterContext.HttpContext.Request.IsAjaxRequest())
            {
                filterContext.Result = new JsonResult
                {
                    Data = new { Message = "Your session has died a terrible and gruesome death" },
                    JsonRequestBehavior = JsonRequestBehavior.AllowGet
                };
                filterContext.HttpContext.Response.StatusCode = 401;
                filterContext.HttpContext.Response.StatusDescription = "Humans and robots must authenticate";
                filterContext.HttpContext.Response.SuppressFormsAuthenticationRedirect = true;
            }
        }
        //base.HandleUnauthorizedRequest(filterContext);
    }
}

что, если я хочу использовать стандартные формы для авторизации перенаправления, когда пользователь не вошел в систему, а также для вызова пользовательских перенаправлений 401, когда у пользователя нет соответствующего разрешения, какие-либо идеи?

DevDave 30.08.2013 15:41

Вы получите обычное перенаправление форм для методов, у которых нет этого атрибута AuthorizeAttribute. Вы также можете просто расширить этот атрибут, указав предложение «else» в if (! FilterContext.IsAuthenticated), в котором вы будете проверять разрешения, а затем самостоятельно настраивать перенаправление.

Timothy Lee Russell 30.08.2013 22:42

Я не вижу, что нам нужно изменить режим аутентификации или тег аутентификации, как говорится в текущем ответе.

Следуя идее @TimothyLeeRussell (кстати, спасибо), я создал настраиваемый атрибут Authorize (проблема с атрибутом @TimothyLeeRussell заключается в том, что генерируется исключение, потому что он пытается изменить filterContext.Result an, который генерирует HttpException, и удалив эту часть, помимо filterContext.HttpContext.Response.StatusCode = 401, код ответа всегда был 200 OK). Итак, я наконец решил проблему, закрыв ответ после изменений.

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class BetterAuthorize : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        if (filterContext.HttpContext.Request.IsAjaxRequest())
        {
            //Set the response status code to 500
            filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
            filterContext.HttpContext.Response.StatusDescription = "Humans and robots must authenticate";
            filterContext.HttpContext.Response.SuppressFormsAuthenticationRedirect = true;

            filterContext.HttpContext.Response.End();
        }
        else
            base.HandleUnauthorizedRequest(filterContext);
    }
}

свойство SuppressFormsAuthenticationRedirect было именно тем, что я искал.

zeocrash 14.07.2015 15:04

Вы можете вызвать этот метод внутри своего действия,

 HttpContext.Response.End();

Пример

public async Task<JsonResult> Return401()
{
    HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
    HttpContext.Response.End();
    return Json("Unauthorized", JsonRequestBehavior.AllowGet);
}

Из MSDN: Метод End заставляет веб-сервер прекращать обработку сценария и возвращать текущий результат. Остальное содержимое файла не обрабатывается.

Другие вопросы по теме