2009-12-10 3 views
6

У нас есть приложение ASP.NET, защищенное аутентификацией форм. Приложение широко использует MS AJAX для вызова своих веб-сервисов.Формы Аутентификация и POST-запросы от AJAX

Когда время проверки подлинности форм и GET -request происходит - все в порядке (пользователь перенаправляется на страницу входа в систему).

НО, когда время проверки подлинности форм из и POST -request происходит (Аякс) - не редирект не происходит, а не приложение возвращается «401 Неразрешенные» и браузер запрашивает имя пользователя и пароль (не формы Войти , но встроенный в браузер браузер). Конечно, вход ЛЮБОЕ имя пользователя/пароль никогда не помогает.

Как с этим справиться?

ОБНОВЛЕНИЕ: После поиска с помощью firebug я только что узнал, что регулярные запросы POST перенаправляют на вход в систему, это только вызовы веб-сервиса, которые вызывают «401 Unauthorizes». Разница между регулярным запросом и веб-службой - это URL. Что "page.aspx" для обычного пост-запроса и "service.asmx/MethodName" для веб-сервисов ...

+1

Вы посмотрели с FireBug, что на самом деле отправлено на сервер и на что он ответил? Встроенная подсказка браузера обычно означает, что ресурс, к которому вы пытаетесь получить доступ, защищен базовой или NTLM-аутентификацией. У вас включена такая аутентификация для частей вашего сайта? –

+0

Да, в настройках IIS у нас есть «windows integrated» authenticaiton on (наряду с «анонимным доступом»). Спасибо, я попробую Firebug – Alex

ответ

2

Хорошо, отвечая на мои собственные призывы.

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

  • Если это GET-запрос - пользователь перенаправляется на страницу входа.
  • Если это POST-запрос на страницу - пользователь перенаправлен на страницу входа.
  • Если это POST-запрос на веб-службы - пользователь получает 401-неавторизованных

вот как ASP.NET работает

И если веб-служба вызывается AJAX (объект xmlHttpRequest) и возвращает 401 - конечно, браузер показывает всплывающее окно входа.

Теперь, что вы должны сделать, это добавить код в Application_PostAuthenticateRequest, который предотвратит бросок 401 для веб-сервисов.

protected void Application_PostAuthenticateRequest(Object sender, EventArgs e) 
{ 
    if (Request.RequestType == "POST" //if its POST 
     && !User.Identity.IsAuthenticated //if user NOT authed 
     && !HasAnonymousAccess(Context) //if it's not the login page 
     ) 
    { 
     //lets get the auth type 
     Configuration config = WebConfigurationManager.OpenWebConfiguration("~"); 
     SystemWebSectionGroup grp = (SystemWebSectionGroup)config.GetSectionGroup("system.web"); 
     AuthenticationSection auth = grp.Authentication; 
     //if it FORMS auth 
     if(auth.Mode== AuthenticationMode.Forms) 
     { 

      //then redirect... this redirect won't work for AJAX cause xmlHttpRequest can't handle redirects, but anyway... 
      Response.Redirect(FormsAuthentication.LoginUrl, true); 
      Response.End(); 

     } 
    } 
} 
public static bool HasAnonymousAccess(HttpContext context) 
{ 
    return UrlAuthorizationModule.CheckUrlAccessForPrincipal(
     context.Request.Path, 
     new GenericPrincipal(new GenericIdentity(string.Empty), null), 
     context.Request.HttpMethod); 
} 
+0

@ jazbit, можете ли вы указать на некоторую оплату, которая говорит о статусе кода 401 для веб-служб, у меня есть сценарий, где я проверяю сеанс ecpiry и делаю перенаправление, которое приводит к клиенту 401. –

+0

Response.End обычно является плохой дел. Обычно вы хотите «response.Redirect (url, False); HttpContext.Current.ApplicationInstance.CompleteRequest(); ' –

1

Я вижу два решения:

механизм (1) "Heart Beat". На каждой странице включить скрипт, который будет «пинг» сервер на некоторый запрос фиктивного АЯКС, как:

<script> 
    setInterval(ping, 60000); // based on comment by John 
    function ping() 
    { 
     $.get('/do/nothing'); 
    } 
</script> 

Таким образом, сеанс не должен истекать, пока окно браузера.

(2) При каждом запросе ajax проверьте состояние ответа. Если в ответе есть «401 несанкционированный» код (или любой другой код, отличающийся от 200), это означает, что сеанс истек, а вместо загрузки ответа в какое-либо диалоговое окно на странице перенаправляет пользователя на страницу входа.

Вывод на основе комментариев:

Лучшим решением было бы объединить два вышеуказанных механизмов. Механизм Heartbeat поможет сохранить сеанс до тех пор, пока страница отображается в браузере. Но это не гарантирует это точно. При завершении сеанса соединение с сервером может быть сломано и возобновлено. Таким образом, вы должны проверить статус ответа в любом случае.

+0

вы можете сделать только 'setInterval (ping, 60000);' передача строки в setInterval не рекомендуется, поскольку это эквивалент eval() –

+0

Вам также нужно будет вызвать setInterval снова в ping() если вы хотите, чтобы он запускался более одного раза –

+0

Любой другой код, отличный от 200, не означает, что сеанс истек. –