Пользовательский атрибут авторизации не работает после развертывания в IIS

Я переопределил метод HandleUnauthorizedRequest в своем приложении asp.net mvc, чтобы убедиться, что он отправляет ответ 401 на несанкционированные вызовы ajax вместо перенаправления на страницу входа. Это отлично работает, когда я запускаю его локально, но мой переопределенный метод не вызывается после развертывания в IIS. Точка отладки вообще не затрагивает мой метод и сразу же перенаправляется на страницу входа.

Это мой код:

public class AjaxAuthorizeAttribute : AuthorizeAttribute
    {
        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            if (filterContext.HttpContext.Request.IsAjaxRequest())
            {
                filterContext.HttpContext.Response.Clear();
                filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;

                filterContext.Result = new JsonResult
                {
                    Data = new
                    {
                        success = false,
                        resultMessage = "Errors"
                    },
                    JsonRequestBehavior = JsonRequestBehavior.AllowGet
                };
                filterContext.HttpContext.Response.End();
                base.HandleUnauthorizedRequest(filterContext);
            }
            else
            {
                var url = HttpContext.Current.Request.Url.AbsoluteUri;
                url = HttpUtility.UrlEncode(url);
                filterContext.Result = new RedirectResult(ConfigurationManager.AppSettings["LoginUrl"] + "?ReturnUrl=" + url);
            }
        }
    }

и у меня есть атрибут [AjaxAuthorize], объявленный поверх моего контроллера. Что может измениться после развертывания в IIS?

Обновление: вот как я тестирую, это очень просто, даже не имеет значения, является ли это запросом ajax или простым обновлением страницы после истечения сеанса входа в систему -

  1. Я развертываю сайт на моем локальном IIS
  2. Авторизоваться на сайте, перейти на главную страницу - "/Home"
  3. Щелкните правой кнопкой мыши ссылку «Выход», «Открыть в новой вкладке» — это гарантирует, что домашняя страница по-прежнему открыта на текущей вкладке, пока сеанс не завершен.
  4. Обновить домашнюю страницу. Теперь здесь точка отладки должна обратиться к моему переопределенному методу HandleUnauthorizedRequest и выполнить условие if/else, а затем перенаправить меня на страницу входа. Но это не так! он просто сразу перенаправляет на страницу входа. Я думаю, что это даже не учитывает мой пользовательский атрибут авторизации.

Однако, когда я запускаю сайт из визуальной студии, все работает нормально, элемент управления входит в точку отладки в моем переопределенном методе и проходит через условие if/else.


person sharath.g    schedule 27.09.2017    source источник
comment
What could be different once it's deployed to IIS? - ConfigurationManager.AppSettings["LoginUrl"] - вы проверили свой файл конфигурации?   -  person NightOwl888    schedule 27.09.2017
comment
Да, я проверил, это указывает на учетную запись/логин. Но проблема заключается в том, что после развертывания в IIS элемент управления даже не входит в метод HandleUnauthorizedRequest моего пользовательского атрибута, даже если я полностью удаляю параметр конфигурации для LoginUrl, он все равно перенаправляется на учетную запись/логин, эта проблема возникает только после развертывания. Я пытался развернуть как в конфигурации отладки, так и в конфигурации выпуска, но та же проблема   -  person sharath.g    schedule 28.09.2017


Ответы (1)


Когда вы развертываете свой веб-сайт в IIS, он по умолчанию будет работать в интегрированном режиме IIS. Обычно это лучший вариант. Но это также означает, что модель запроса/ответа HTTP не полностью инициализируется во время проверки авторизации. Я подозреваю, что это приводит к тому, что IsAjaxRequest() всегда возвращает false, когда ваше приложение размещено в IIS.

Кроме того, реализация HandleUnauthorizedRequest по умолчанию выглядит так:

    protected virtual void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        // Returns HTTP 401 - see comment in HttpUnauthorizedResult.cs.
        filterContext.Result = new HttpUnauthorizedResult();
    }

Фактически, вызывая base.HandleUnauthorizedRequest(context), вы перезаписываете экземпляр JsonResult, который вы устанавливаете, экземпляром HttpUnauthorizedResult по умолчанию.

Не зря они называются фильтрами. Они предназначены для фильтрации запросов, которые входят в часть логики, а не для фактического выполнения этой части логики. Обработчик (производный класс ActionResult) должен выполнять эту работу.

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

public class AjaxAuthorizeAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        filterContext.Result = new AjaxHandler();
    }
}

public class AjaxHandler : JsonResult
{
    public override void ExecuteResult(ControllerContext context)
    {
        var httpContext = context.HttpContext;
        var request = httpContext.Request;
        var response = httpContext.Response;
        if (request.IsAjaxRequest())
        {
            response.StatusCode = (int)HttpStatusCode.Unauthorized;

            this.Data = new
            {
                success = false,
                resultMessage = "Errors"
            };
            this.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
            base.ExecuteResult(context);
        }
        else
        {
            var url = request.Url.AbsoluteUri;
            url = HttpUtility.UrlEncode(url);
            url = ConfigurationManager.AppSettings["LoginUrl"] + "?ReturnUrl=" + url;
            var redirectResult = new RedirectResult(url);
            redirectResult.ExecuteResult(context);
        }
    }
}

ПРИМЕЧАНИЕ. Приведенный выше код не тестировался. Но это должно заставить вас двигаться в правильном направлении.

person NightOwl888    schedule 04.10.2017