Проблема с методом вызова к действию Ajax на контроллере, требующем аутентифицированного пользователя - PullRequest
4 голосов
/ 28 августа 2009

Используя технику, которую я нашел в одной из недавних книг ASP.NET MVC, у меня есть метод действия на контроллере, который возвращает частичное представление для запроса ajax и полный результат действия для обычного запроса get - он проверяет свойство IsAjaxRequest объекта Request, чтобы определить, какой тип actionresult возвращается. Частичное представление, возвращаемое методом действия, возвращает HTML для отображения таблицы записей из базы данных. Контроллер, который содержит метод действия, помечен атрибутом Authorize, так что только зарегистрированные пользователи могут вызывать методы контроллера. Я использую аутентификацию форм с 30-минутным таймаутом и скользящим сроком действия.

Проблема возникает после того, как истекло 30-минутное время ожидания пользователя. Поскольку контроллер помечен атрибутом Authorize, вызов метода действия после истечения срока действия перенаправляет пользователя на страницу входа. Однако, поскольку это ajax-вызов, HTML-код моей страницы входа возвращается и отображается в середине страницы, которая должна содержать таблицу записей HTML, которая обычно возвращается методом действия в частичном представлении. Вызов ajax на самом деле не дает сбоя, просто возвращает html для неправильной страницы.

Кто-нибудь сталкивался и имел дело с этой проблемой? Я пытаюсь избежать перемещения всего моего серверного кода, который обрабатывает вызовы ajax, в отдельный контроллер, который не требует аутентифицированного пользователя, но на данный момент это кажется моей единственной альтернативой. Даже это не приведет к поведению, которое я ожидаю, потому что оно позволит пользователю продолжать использовать веб-страницу даже после того, как истечет 30-минутный тайм-аут - он не будет перенаправлен на страницу входа.

Спасибо за любой совет.


Редактировать

Казалось бы, приведенное ниже решение с пользовательским атрибутом AuthorizeAttribute направило меня в правильном направлении, но я даже не могу добраться до этого кода. Похоже, что код в пользовательском атрибуте AuthorizeAttribute никогда не достигается после истечения времени ожидания. Кажется, что аутентификация форм вызывает перенаправление на страницу входа задолго до кода атрибута. Пользовательский AuthorizeAttribute является единственным на моем контроллере. У меня также есть следующие значения web.config (значение тайм-аута установлено очень низким, чтобы вызвать тайм-аут для тестирования):

<authentication mode="Forms">
        <forms loginUrl="~/Account/Login" timeout="1" slidingExpiration="true" defaultUrl="~/ErrorReport/Index" requireSSL="true" protection="All"/>
</authentication>
<authorization>
        <deny users="?"/>
        <allow users="*"/>
</authorization>
<location path="Content">
        <system.web>
            <authorization>
                <allow users="*"/>
            </authorization>
        </system.web>
    </location>
<location path="Scripts">
        <system.web>
            <authorization>
                <allow users="*"/>
            </authorization>
        </system.web>
</location>

Мешают ли элементы 1017 * web.config? Разве я не должен использовать их с ASP.NET MVC?

Ответы [ 2 ]

6 голосов
/ 28 августа 2009

У меня фактически есть пост в блоге об этой очереди, который я добавлю к комментарию, когда он будет опубликован, но в настоящее время вот что происходит.

На высоком уровне, когда среда выполнения ASP.NET видит код ответа 401, он автоматически преобразует его в перенаправление и отправляет пользователя на страницу входа. То, что вы хотите сделать, это обойти это 401.

В MVC, когда вы используете AuthorizeAttribute, он проверяет, авторизован ли пользователь, и, если нет, возвращает HttpUnauthorizedResult. Это в основном заставляет среду выполнения перенаправлять пользователя на страницу входа. Что вы хотите сделать, это переопределить это поведение.

Для этого расширьте атрибут AuthorizeAttribute следующим образом:

public class AuthorizeWithAjaxAttribute : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        base.OnAuthorization(filterContext);

        if (filterContext.Result is HttpUnauthorizedResult && filterContext.HttpContext.Request.IsAjaxRequest())
        {
            filterContext.HttpContext.Response.StatusCode = 200;
            filterContext.Result = /* Some result recognized by the client */
        }
    }
}

Когда вы делаете запрос AJAX, и данные ответа равны тому, что вы возвращаете как результат контекста фильтра, просто перенаправьте пользователя на страницу входа через javascript.

1 голос
/ 28 августа 2009

Да, эта проблема довольно распространена. У него также есть простое решение - в части Javascript, которая обрабатывает ответ AJAX, проверьте время ожидания перед использованием ответа. Если истекло время ожидания, перенаправьте пользователя на страницу входа.

С другой стороны, если серверный скрипт сам проверяет время ожидания сеанса (что, по-видимому, соответствует вашему случаю), он становится еще проще. Не возвращайте всю страницу входа в систему, вместо этого просто верните флаг, как 'need_login'. Далее, просто напишите обработчик Javascript, чтобы проверить, является ли возвращаемое значение 'need_login', и загрузите страницу входа, если true.

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