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

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

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

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

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

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

В classическом ASP.NET вы получаете код ответа 401 http при вызове 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; } } 

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

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

//web.config

   

// controller

 [Authorize(Roles = "Administrator,User"), Response302to401] [AcceptVerbs("Get")] public async Task GetDocuments() { string requestUri = User.Identity.Name.ToLower() + "/document"; RequestKeyHttpClient, string> client = new RequestKeyHttpClient, string>(requestUri); var documents = await client.GetManyAsync>(); 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); } } 

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

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

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

Следуя идее @TimothyLeeRussell (спасибо, кстати), я создал настраиваемый атрибут Authorize (проблема с именем @TimothyLeeRussell заключается в том, что исключение выбрано потому, что он пытается изменить filterContext.Result a, который генерирует исключение HttpException и удалив эту часть, помимо фильтраContext.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); } } 

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

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

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

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

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

  HttpContext.Response.End(); 

пример

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

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

  • Получить дополнительные данные из структуры MVC5. Поставщик идентификации OAuth / OWin с внешним поставщиком авторизации
  • Параллельный просмотр стороны частичного просмотра диалогового windows Jquery при нажатии кнопки «Сохранить»
  • Как перенаправитьToAction в ASP.NET MVC без потери данных запроса
  • ASP.NET MVC - проверка подлинности HTTP
  • Что такое дочернее действие MVC?
  • ASP.NET MVC ActionLink и метод post
  • Получение имени controllerа и метода действий в представлении в ASP.Net MVC
  • Идентификация ASP.NET DbContext путаница
  • Производительность бритвы ASP.NET MVC 3
  • При обработке отчета произошла ошибка. Отчеты -RLDC в ASP.NET MVC
  • @ Html.Action в Core Asp.Net
  • Interesting Posts

    Как устранить ошибку «java.net.BindException: Address уже используется: JVM_Bind»?

    Получить значения из файла свойств с помощью Groovy

    tags header / footer / nav – что происходит с ними в IE7, IE8 и браузерах, чем не поддерживают HTML5?

    Является ли структура агрегации Mongodb быстрее, чем карта / сокращение?

    Что означает «On-link» в результате команды «route print»?

    Добавление кнопки OnClick в сообщение в уведомлении

    Автоматически разделять большие .mov видеофайлы на более мелкие файлы на черных кадрах (смена сцены)?

    nodejs, как читать нажатия клавиш от stdin

    Могу ли я безопасно подключить внутренний штыревой блок USB 2.0 / 1.1 к заголовку материнской платы USB3.0?

    Сгенерировать PDF из документации API Swagger

    Будет ли использовать переменные утечки goto?

    Почему при использовании этой составной формы происходит замена значений с помощью XOR?

    Как использовать локализацию в C #

    Run Time Machine на том же диске, который содержит файлы Windows

    Перегрузка Java-методом + двойная отправка

    Давайте будем гением компьютера.