2015-04-23 15 views
14

Czy mogę usunąć to pytanie? Wyjaśniłem, jaki był problem, a nie było IIS ... Zobacz moją odpowiedź poniżej dla wyniku.Dziwne przekierowanie AJAX 401 z IIS

oryginalne pytanie Pracuję nad aplikacji ASP.Net MVC i uruchomić w celu dziwny problem z przepisywania URL przekierowania i żądań AJAX.

Dodałem następującą regułę przepisywania do mojego Web.config w witrynie głównej.

<rewrite> 
    <rules> 
     <rule name="Account" stopProcessing="true"> 
      <match url="^SubApp/Account/(.*)$" /> 
      <action type="Redirect" url="Account/{R:1}" redirectType="Found" /> 
     </rule> 
    </rules> 
</rewrite> 

Wszystko wydaje się działać ok, jeśli mogę użyć Permanent lub TemporaryredirectType w config, ale nie ze strony błędu HTTP Error 401.0 - Unauthorized IIS.

Kiedy wysyłam normalne żądanie GET za pośrednictwem przeglądarki do działania, które wywołałoby tę regułę, np. https://some-site/SubApp/Account/Settings, a następnie otrzymuję 302 Found i nagłówek lokalizacji jest ustawiony na oczekiwany URL https://some-site/Account/Settings, a odpowiednia strona jest renderowana.

Jednak gdy wykonuję żądanie GET za pośrednictwem AJAX JQuery, tj. $.get('https://some-site/SubApp/Account/Settings'), zwrócony kod stanu odpowiedzi to 401 Unauthorized, ale nadal ma odpowiedni nagłówek położenia.

Treść odpowiedzi to standardowa strona błędu IIS HTTP Error 401.0 - Unauthorized.

Weirdly wszystko wydaje się działać dobrze, jeśli używam typów przekierowania Permanent lub Temporary w konfiguracji, ale nie tylko z Found.

/SubApp to osobna aplikacja, która znajduje się poniżej głównej witryny pod numerem /.

Co się dzieje?

ekranu

redirectType="Permanent" Permanent Redirect

redirectType="Found" Found Redirect

redirectType="Temporary" Temporary Redirect

Jak widać na screenach jedynym di fence to redirectType określony w Web.config.

Jak widać przekierowania działają zgodnie z oczekiwaniami, z wyjątkiem typu przekierowania Found, który prawdopodobnie uzyska odpowiedź o przekierowaniu na ten sam adres URL, co pozostałe.

+0

Czy możesz dodać kod. – Mairaj

+0

Czy możesz dodać zrzut ekranu ruchu sieciowego dla obu przypadków (działający/nie działa)? – drax

+0

Mogę to zrobić, ale to całkiem '$ .get ("/BMS/Account/Settings ")'. Zaktualizuję pytanie kilkoma zrzutami ekranu ... – phuzi

Odpowiedz

5

Ahhhh, wiesz, kiedy przez chwilę nie myślisz o czymś, a nagle dostajesz inspirację ... Cóż, zdarzyło się zeszłej nocy i znalazłem ten mały samorodek w celu "naprawienia" nacisków MVC na przekierowanie żądań AJAX, gdy uwierzytelnianie nie powiedzie się ...

protected void Application_EndRequest() 
{ 
    var context = new HttpContextWrapper(Context); 
    // MVC retuns a 302 for unauthorized ajax requests so alter to request status to be a 401 
    if (context.Response.StatusCode == 302 && context.Request.IsAjaxRequest() && !context.Request.IsAuthenticated) 
    { 
     context.Response.Clear(); 
     context.Response.StatusCode = 401; 
    } 
} 

I unsuprisingly, context.Request.IsAuthenticated zawsze jest fałszywe, ponieważ wydaje się zresetować przez przekierowanie.

Zaktualizował to, przy niewielkiej pomocy z Branislav Abadjimarinov's blog post na ten temat.

protected void Application_EndRequest() 
{ 
    var context = new HttpContextWrapper(Context); 
    // MVC returns a 302 for unauthorized ajax requests so alter to request status to be a 401 

    if (context.Response.StatusCode == 302 && context.Request.IsAjaxRequest()) 
    { 
     //Unfortunately the redirect also clears the results of any authentication 
     //Try to manually authenticate the user... 
     var authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName]; 
     if (authCookie != null) 
     { 
      var authTicket = FormsAuthentication.Decrypt(authCookie.Value); 
      if (authTicket != null && !authTicket.Expired) 
      { 
       var roles = authTicket.UserData.Split(','); 
       HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(new FormsIdentity(authTicket), roles); 
      } 
     } 

     if (!context.Request.IsAuthenticated) 
     { 
      context.Response.Clear(); 
      context.Response.StatusCode = 401; 
     } 

    } 
} 

Wszystko działa zgodnie z oczekiwaniami.

Pytanie tylko czy należy usunąć to pytanie?

+4

Nie usuwaj go, może być pomocny dla przyszłych użytkowników –

0

Spójrz na to Cannot handle 302 redirect in ajax and why? [duplicate], wygląda na to, że przeglądarka internetowa widzi Found-302 i wykonuje na nim akcję.

+0

Sprawdzę dwa razy jutro, ale sesja jest w pełni uwierzytelniona i widzę zarówno 301 z nagłówkiem lokalizacji, jak i kolejne żądanie przeglądarki do nowej lokalizacji z odpowiedzią o statusie 200, gdy jest ustawiona na "Trwałe". dokładnie tak samo, z wyjątkiem kodu statusu 307 dla pierwszej odpowiedzi, gdy "redirectType" jest ustawione na "Tymczasowe". Kiedy jest ustawiony na 'Found', otrzymuję 401, ale dziwnie nagłówek lokalizacji jest ustawiony na zasób, na który spodziewałem się przekierowania. Nie próbuję obsługiwać przekierowania ręcznie, a nagłówek lokalizacji wskazuje właściwy zasób. – phuzi

+0

Brian, może brakuje mi czegoś, ale odsyłany link wydaje się polegać na tym, aby nie przekierowywać nieautoryzowanych żądań na stronę autoryzacji Przekierowania strony Bc nie mogą się zdarzyć w ajax. Jeśli tak, to moje zrozumienie kwestii OP jest czymś zupełnie innym. –

Powiązane problemy