2012-03-29 13 views
15

Mamy aplikację ASP.NET MVC 2 (.NET 4) działającą w systemie Windows Azure (najnowsza wersja systemu operacyjnego 2.x) z dwiema instancjami roli internetowej.Dlaczego wyjątek HttpAntiForgeryException występuje losowo, nawet w przypadku statycznego klucza komputera?

Używamy tokena przeciw fałszowaniu dostarczonego przez MVC dla wszystkich żądań POST, a ustawiliśmy Statyczny klucz maszynowy w web.config, więc wszystko działa na wielu komputerach i na różnych restartach. 99,9% przypadków działa idealnie.

Co jakiś czas rejestrujemy wyjątek HttpAntiForgeryException z komunikatem "Wymagany token zabezpieczający przed fałszowaniem nie został dostarczony lub był niepoprawny."

Wiem, że problem może polegać na tym, że pliki cookie nie są dozwolone w przeglądarce, ale sprawdziliśmy, że pliki cookie są włączone i poprawnie wysyłane.

Błąd występuje w różnych przeglądarkach i oczywiście powoduje problemy dla użytkowników, ponieważ muszą oni powtórzyć operację lub mogą utracić niektóre dane. Wystarczy powiedzieć, że nie byliśmy w stanie odtworzyć problemu lokalnie, ale dzieje się tak tylko na Windows Azure.

Dlaczego tak się dzieje? Jak możemy tego uniknąć?

+0

Sprawdziłem z ochroniarzami (w zespole MVC), a Darin prawdopodobnie ma rację - nazwa użytkownika prawdopodobnie się zmieniła. – RickAndMSFT

Odpowiedz

0

Istnieje kilka opcji, które można wypróbować. Możesz spróbować podłączyć do komputera i przejrzeć dziennik zdarzeń, aby dowiedzieć się, czy możesz uzyskać więcej informacji na ten temat w odniesieniu do tego, gdzie to się dzieje. Jeśli to nie pomoże, możesz użyć DebugDiag lub innego narzędzia do przechwycenia zrzutu procesu (DebugDiag pozwoli ci uchwycić jeden w czasie tego wyjątku). A potem spójrz na to, aby zobaczyć, co się dzieje.

Jeśli nie możesz tego odgadnąć, zawsze możesz utworzyć zgłoszenie do pomocy technicznej w firmie Microsoft, aby pomóc Ci je zbadać.

7

Token zapobiegający fałszowaniu zawiera nazwę użytkownika aktualnie podłączonego użytkownika, gdy jest emitowany. Sprawdzając jego aktualność, aktualnie podłączony użytkownik jest porównywany z tym, który był używany podczas wysyłania tokena. Na przykład, jeśli masz formularz, w którym użytkownik nie jest jeszcze uwierzytelniony i emitujesz token zabezpieczający przed fałszowaniem, nie będzie w nim przechowywana żadna nazwa użytkownika. Jeśli po przesłaniu formularza uwierzytelnisz użytkownika, token nie będzie już ważny. To samo dotyczy wylogowywania.

Oto jak wygląda metoda Weryfikuj:

public void Validate(HttpContextBase context, string salt) 
{ 
    string antiForgeryTokenName = AntiForgeryData.GetAntiForgeryTokenName(null); 
    string str2 = AntiForgeryData.GetAntiForgeryTokenName(context.Request.ApplicationPath); 
    HttpCookie cookie = context.Request.Cookies[str2]; 
    if ((cookie == null) || string.IsNullOrEmpty(cookie.Value)) 
    { 
     throw CreateValidationException(); 
    } 
    AntiForgeryData data = this.Serializer.Deserialize(cookie.Value); 
    string str3 = context.Request.Form[antiForgeryTokenName]; 
    if (string.IsNullOrEmpty(str3)) 
    { 
     throw CreateValidationException(); 
    } 
    AntiForgeryData data2 = this.Serializer.Deserialize(str3); 
    if (!string.Equals(data.Value, data2.Value, StringComparison.Ordinal)) 
    { 
     throw CreateValidationException(); 
    } 
    string username = AntiForgeryData.GetUsername(context.User); 
    if (!string.Equals(data2.Username, username, StringComparison.OrdinalIgnoreCase)) 
    { 
     throw CreateValidationException(); 
    } 
    if (!string.Equals(salt ?? string.Empty, data2.Salt, StringComparison.Ordinal)) 
    { 
     throw CreateValidationException(); 
    } 
} 

Jednym z możliwych sposobów do debugowania to przekompilować ASP.NET MVC z kodem źródłowym i zalogować dokładnie, w którym z przypadków jeżeli wpiszesz gdy wyjątek Jest rzucony.

+0

Pracownicy bezpieczeństwa zespołu ASP.NET MVC są zgodni, nazwa użytkownika prawdopodobnie uległa zmianie. Teraz, gdy MVC jest open source, możesz zbudować gałąź diagnostyczną. Jedna drobna uwaga, token AF NIE zawiera nazwy użytkownika - kod pokazuje, że nazwa użytkownika pochodzi z tokena formularza, a nie z tokena cookie. – RickAndMSFT

+0

Problem polega na tym, że nie używamy uwierzytelniania ASP.NET i nigdy nie ustawiamy użytkownika/tożsamości. Czy nazwa użytkownika może zmienić się sama (pod warunkiem, że aplikacja działa jako usługa sieciowa na platformie Azure)? –

+0

Czy próbowałeś rekompilować ASP.NET MVC z kodu źródłowego i śledzenia, w takim przypadku weryfikacja antywłamaniowa nie powiedzie się? –

15

Wpadłem na to ostatnio i znalazłem dwie przyczyny.

1. Przeglądarka przywraca ostatnią sesję na otwarte do strony, która jest buforowane

Jeśli masz stronę, która jest cachable który wykonuje post do serwera (tj zabezpieczającym będzie dalej), a użytkownik ma swoje zestaw przeglądarki, aby przywrócić ostatnią sesję podczas uruchamiania (ta opcja istnieje w chrome) strona zostanie wyrenderowana z pamięci podręcznej. Jednak plik cookie weryfikacji żądania nie będzie dostępny, ponieważ jest to plik cookie sesji przeglądarki i jest odrzucany po zamknięciu przeglądarki. Odkąd ciasteczko zniknęło, otrzymujesz wyjątek przeciwko fałszerstwu. Rozwiązanie: Zwróć nagłówki odpowiedzi, aby strona nie była przechowywana w pamięci podręcznej (np. Cache-Control: private, no-store).

2.Stan wyścigu w przypadku otwarcia więcej niż jednej zakładki przy uruchomieniu witryny

Przeglądarki mają opcję otwierania zestawu kart podczas uruchamiania. Jeśli więcej niż jedna z nich trafi na twoją stronę, która zwróci plik cookie weryfikacji żądania, możesz trafić w stan wyścigu, w którym plik cookie weryfikacji żądania zostanie nadpisany. Dzieje się tak, ponieważ więcej niż jedno żądanie trafia na serwer od użytkownika, który nie ma zestawu plików cookie weryfikacji żądania. Pierwsze żądanie jest obsługiwane i ustawia plik cookie weryfikacji żądania. Następnie przetwarzane jest drugie żądanie, ale nie wysłano pliku cookie (który nie został jeszcze ustawiony w momencie żądania), więc serwer generuje nowy. Nowa nadpisuje pierwszą, a teraz strona ta otrzyma wyjątek od żądania ochrony przed oszustwami, gdy następnie wykona post. Środowisko MVC nie obsługuje tego scenariusza. Ten błąd został zgłoszony zespołowi MVC w firmie Microsoft.

+0

Widzę także stan 2. To zdarza się tylko pierwszemu użytkownikowi. Po załadowaniu strony dla tego pierwszego użytkownika już się to nie zdarza. – GnomeCubed

1

Posiadam kilka aplikacji internetowych MVC3, które są regularnie odwiedzane. Większość z nich polega na tym, że klient nie wysyła treści POST. I większość z nich to IE8 z powodu jakiegoś błędu z prośbami ajaxowymi poprzedzającymi zwykły post. Jest to poprawka dla IE, który wydaje się dotyczyć objawy, których rodzaj dowodzi, że jest to błąd klienta w tych przypadkach

http://support.microsoft.com/?kbid=831167

Istnieje kilka dyskusje o numerze całym Internecie, nic użytecznego choć , ja na pewno nie jestem o bałagan z keep-alive limity czasu co jest sugerowane „rozwiązanie” w niektórych miejscach ...

https://www.google.com/search?q=ie8+empty+post+body

nigdy nie byłem w stanie odtworzyć go z różnymi próbami zerwij połączenia między POSTS, więc obawiam się, że nie mam prawdziwego rozwiązanie dla przypadku pustych POE IE. Sposób, w jaki go trochę złagodziliśmy, polega na upewnieniu się, że nigdy nie używamy metody POST podczas pobierania danych przez ajax.

Jeśli logujesz pełne żądanie, sprawdź, czy treść POST jest pusta, a jeśli tak jest, prawdopodobnie będzie to starszy IE. I nie mam na myśli długości treści: 0, zazwyczaj będzie mieć długość treści, która wydaje się poprawna w nagłówkach, ale nie będzie dosłownie nic po nagłówkach w żądaniu.

Problem jako całość jest dla mnie nadal zagadką, ponieważ wciąż otrzymujemy sporadyczny wyjątek tam, gdzie jest kompletna treść POST. Nasze nazwy użytkownika nigdy się nie zmieniają, a nasze klucze również są statyczne, nie próbowałem dodawać debugowania do źródła, jeśli kiedykolwiek się do tego zabiorę, zgłosimy swoje ustalenia.

0

Zetknąłem się z podobnymi problemami z moim domowym kodem przeciw fałszerstwem, który jest koncepcyjnie bardzo podobny do mechanizmu MVC. Najczęściej problem wydaje się występować, ponieważ pojawiają się współczesne przeglądarki, które chcą wyświetlać buforowane kopie stron określone jako niebuforowane.

Próbowałem wszystkich kombinacji dyrektyw bez pamięci podręcznej strony, ale czasami nadal wyświetlane są strony z pamięci podręcznej.

Odkryłem, że lepszym rozwiązaniem jest przechwycenie zdarzenia onbeforeunload dla strony i jawne wyczyszczenie wartości ukrytego pola wprowadzania zawierającego wartość tokena w DOM.

Jeśli załadowana kopia strony jest zapisana w pamięci podręcznej, wygląda na to, że zawiera wyczyszczoną wartość pola wejściowego. I wtedy przetestować tę funkcję w gotowym dokumencie i przeładować stronę, jeśli to konieczne:

window.location.reload(true); 

Wydaje się dość skutecznie pracować i podejrzewam dla MVC kodu przed fałszerstwem też to może.

Powiązane problemy