2009-05-15 11 views
5

Budując system zarządzania treścią, który zawiera jquery ajax do swojego GUI, natrafiłem na przeszkodę. Wygląda na to, że niektórzy klienci zbyt długo zastanawiają się nad tym, co zamierzają napisać, i dlatego sesja serwera wylogowuje ich, naturalnie jest to sieć, której nie mają pojęcia. Kiedy próbują przesłać zmiany, używam wywołania ajax do serwera, aby zapisać dane.Sprawdzanie autoryzacji http w mvc przed wysłaniem formularza ajaxowego

Następnym działaniem jest to, że aplikacja serwera MVC zwróci status "401 Nieautoryzowany". Mógłbym wtedy pobrać mój obiekt ajax jquery, aby poprosić użytkownika o zalogowanie, a następnie ponownie wysłać zmiany po autoryzacji użytkownika.

Jednak to, co faktycznie jest zwracane z aplikacji MVC, to status "Znaleziono 302" i przekierowanie do strony z formularzem logowania. Strona formularza logowania zwraca kod statusu "200 OK", a obiekt ajax jquery wywołuje zdarzenie sukcesu, które informuje użytkownika, że ​​wszystko przebiegło pomyślnie, ponieważ tak mówi aplikacja MVC.

Czy istnieje sposób, aby uzyskać aplikację MVC do odtwarzania w sposób, w jaki powinienem, czy muszę zmodyfikować moje zdarzenia ajax jquery, aby wykryć stronę logowania?

Aktualizacja:

Użyłem reflektor do obejrzenia w kodzie MVC i atrybut autoryzacji, zwracają NotAuthorizedResult kod który jest poniżej (0x191 = 401)

public override void ExecuteResult(ControllerContext context) 
{ 
    if (context == null) 
    { 
     throw new ArgumentNullException("context"); 
    } 
    context.HttpContext.Response.StatusCode = 0x191; 
} 

Myślę, że być może HttpModule autoryzacji formularzy widzi 401 i wymusza przekierowanie.

Odpowiedz

6

można spróbować czegoś takiego:

void context_EndRequest(object sender, EventArgs e) 
    { 
     var app = sender as HttpApplication; 
     var response = app.Response; 
     var request = app.Request; 

     if ((response.StatusCode == 302) && IsAjaxRequest(request)) 
      response.StatusCode = 401; 
    } 

w HttpModule, to będzie po moduł FormsAuth kolejno więc skorygować kod stanu. Nie ładne, ale skuteczne.

+0

W .Net 4.0 (być może inne wersje też, nie wiem), FormsAuthentication wykonuje przekierowanie w procedurze obsługi EndRequest.Odkryłem, że FormsAuth nie przetworzył odpowiedzi, jeśli użyłem EndRequest, ale użycie zdarzenia PreSendRequestHeaders zadziałało o wiele lepiej (pojawia się po EndRequest). Dzięki za ten świetny post. – womp

5

Bardzo podoba mi się to rozwiązanie. Zmieniając odpowiedź 302 na żądania ajaxa na 401, pozwala skonfigurować ajax po stronie klienta, aby monitorować zapytanie ajaxowe szukające 401 i jeśli znajdzie przekierowanie na stronę logowania. Bardzo prosty i skuteczny.

Global.asax:

protected void Application_EndRequest() 
{ 
    if (Context.Response.StatusCode == 302 && 
     Context.Request.Headers["X-Requested-With"] == "XMLHttpRequest") 
    { 
     Context.Response.Clear(); 
     Context.Response.StatusCode = 401; 
    } 
} 

Client Side Kod:

$(function() { 
     $.ajaxSetup({ 
     statusCode: { 
      401: function() { 
      location.href = '/Logon.aspx?ReturnUrl=' + location.pathname; 
      } 
     } 
     }); 
    }); 
1

Odkryłem, że bardziej lekkie podejście jest po prostu dodać niestandardowy nagłówek HTTP do strony logowania, a następnie sprawdzić na obecność tego w wywołaniu powodzenia AJAX.

Tzn. w LoginController (jest to projekt MVC, ale ta sama zasada powinna mieć zastosowanie do innych rozwiązań ASP.NET):

public ActionResult Login(string returnUrl = "") 
{ 
    Response.AddHeader("X-Unauthorized", "true"); 
    ... 

a następnie w po stronie klienta AJAX Handler:

success: function(data, textStatus, jqXhr) 
{ 
    if (jqXhr.getResponseHeader("X-Unauthorized")) 
    { 
     ... 

to działa przynajmniej dla mnie.