Код ответа 401 для запросов JSON с ASP.NET MVC - PullRequest
35 голосов
/ 24 сентября 2008

Как отключить стандартную обработку ASP.NET кода ответа 401 (перенаправление на страницу входа) для запросов 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

Ответы [ 7 ]

24 голосов
/ 02 июля 2009

В классическом 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;
    }
}
18 голосов
/ 25 сентября 2008

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

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

9 голосов
/ 18 июня 2013

Я хотел получить проверку подлинности с помощью форм и вернуть 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);
    }
}
2 голосов
/ 20 декабря 2014

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

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

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

    protected void Application_PreSendRequestHeaders(object sender, EventArgs e) {
        if (Response.StatusCode == 401) {
            Response.Clear();
            Response.Redirect(Response.ApplyAppPathModifier("~/Login.aspx"));
            return;
        }
    }
1 голос
/ 31 марта 2015

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

 HttpContext.Response.End();

Пример

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

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

1 голос
/ 24 сентября 2008

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...