2009-09-08 28 views
7

Mam aplikację komunikującą się z serwerem korzystającym z uwierzytelniania HTTP Digest.Używanie uwierzytelniania HTTP Digest w telefonie iPhone

Wydaje mi się, że zarządzanie sesją w iPhonie jest dla nas dosyć "czarną skrzynką". Czy to prawda, że ​​nie możemy zobaczyć, w jaki sposób framework obsługuje/utrzymuje sesje http?

Jeśli jestem tu po prostu przyćmiony, czy ktoś by chciał wyjaśnić, jak prawdopodobnie obsługiwać uwierzytelnianie HTTP Digest na iPhonie?

Mój podstawowy prowadzony przez to:

  • Złóż wniosek do zabezpieczonej url
  • serwer wysyła 401
  • klient tworzy i utrzymuje poświadczeń i przekazuje je z powrotem do serwera
  • serwer weryfikuje poświadczenia, wypełnia żądanie, jeśli jest zweryfikowane, wysyła kolejne 401, jeśli nie.
  • zrobić kolejny wniosek do bezpiecznego adresu URL
  • wniosków serwera autoryzacji ponownie ........

ta działa na pojedynczych wniosków, ale jeśli zrobię każde kolejne żądania, wnioski o zezwolenie na serwer jeszcze raz. Serwer utrzymywał sesję dla określonego użytkownika, ale iPhone nie wysyła żądania w tej samej sesji z jakiegoś powodu ... Dlatego serwer musi wyrzucić obiekt uwierzytelniania i utworzyć nowy za każdym razem, gdy klient wysyła żądanie do zabezpieczonego adresu URL.

Jestem pewien, że to nie jest prawidłowe zachowanie.

Jeśli przyjrzymy się, jak przeglądarka zachowuje się w tej sytuacji:

  • przeglądarka żąda danych z bezpiecznym url
  • serwer wysyła 401
  • przeglądarka poprosi użytkownika o uwierzytelnienie, utrzymuje ją, przekazuje je do serwera
  • Serwer weryfikuje dane uwierzytelniające, zwraca dane, jeśli jest zweryfikowany, wysyła kolejne 401, jeśli nie.
  • Kolejne żądania dotyczące bezpiecznych adresów URL nie są monitowane o poświadczenia, ponieważ przeglądarka zarządza sesją.

Tworzę NSURLCredential i utrzymuję go w NSURLCrendtialStorage. Następnie, gdy aplikacja otrzyma polecenie "didReceiveAuthenticationChallenge", pobierze poświadczenie z pamięci i odeśle je, tworząc poświadczenie, jeśli nie istnieje (przy pierwszym żądaniu).

Każda pomoc zostanie bardzo doceniona. Dzięki.

Odpowiedz

3

Pierwszą rzeczą jest zapomnieć o sesjach HTTP, ponieważ te nie wchodzą w interakcje z aktywnymi logowaniem uwierzytelniania Digest (istnieje pewien rodzaj informacji o sesji, ale jest inny).

Rzeczywiście, jednym z głównych powodów używania Digest, jest nieużywanie sesji tylko po to, aby utrzymać stan zalogowania. Sesje są ciężkie i szkodzą skalowalności.

Nie mogę powiedzieć na pewno, jaki jest twój problem, ale wiem, co chciałbym sprawdzić na początku, co jest poprawnym użyciem nieaktualnego i prawidłowego tworzenia nonces.

User-agent może obsługiwać uwierzytelnianie tylko bez żądania użytkownika, jeśli zostanie poproszony o obsługę tego samego numeru, lub w innym przypadku, do którego dojdzie później (łatwiej wyjaśnić to w tej kolejności).

Jeśli masz taki sam numer używany w każdym żądaniu, agent użytkownika będzie nadal go używać wraz z "ha1" od użytkownika/przepustki do żądania kolejnych zasobów. Odbywa się to w sposób prewencyjny, więc wyzwanie nigdy się nie zdarza.

Oczywiście użycie tego samego elementu wprowadza element niepewności, ponieważ ataki powtórki stają się banalne dla każdego, kto może wywąchać ruch. Nonces będzie musiał zmieniać się regularnie.

W związku z tym, jeśli otrzymasz żądanie od agenta użytkownika z nieprawidłowym nagłówkiem autoryzacji, ale powodem jego nieważności jest to, że numer jest nieprawidłowy (używa się wygasłego), to w wyzwaniu wpisz "stale = true" "(domyślnie false). To informuje użytkownika-agenta, że ​​twój powód odrzucenia jest nonce jest nieaktualny (oczywiście inne informacje mogą być również błędne, ale to nie ma znaczenia, ponieważ nie pozwolisz mu grać tak czy inaczej).

Po otrzymaniu takiego nieaktualnego znaku = true agent użytkownika będzie wiedział, że nie jest autoryzowany, ale zamiast zażądać podania użytkownika (lub wyrzucenia wyjątku, jeśli jest to komponent bez interfejsu użytkownika), spróbuje ponownie użyć starych kryteriów. nowy nonce.

Nie mogę stwierdzić, czy to wszystko wpływa na ciebie, ale sposób, w jaki nonces i stichy są zdeterminowane i sygnalizowane, jest z pewnością pierwszą rzeczą, na którą patrzę.

+0

Jasarien, Czy mogę wziąć kleszcza w ten sposób, aby postawić cię na dobrej drodze? (dla mojej ciekawości i być może korzyści kogoś innego znajdującego ten sam problem). –

1

Napisałem aplikację na iPhone'a z uwierzytelnianiem HTTP i doświadczyłem tego, co opisujesz. (Moja aplikacja używa podstawowego uwierzytelniania zamiast uwierzytelniania digest, ale nie ma to dużego znaczenia.)

Przyczyna problemu leży po stronie iPhone'a. Serwer musi odpowiedzieć 401, jeśli iPhone nie wysyła poświadczeń w nagłówku żądania HTTP. W rzeczywistości nie jest to tak łatwe, nawet jeśli poświadczenie zostanie zapisane w pamięci poświadczeń.

To dziwne zachowanie miało poważny wpływ na szybkość aplikacji, ponieważ każde żądanie spowodowało dwie wycieczki w obie strony do serwera zamiast jednego (pierwszy o statusie 401, drugi o wartości 200).

mam rozwiązać go poprzez ręczne ustawienie poświadczeń w nagłówku żądania HTTP:

NSString* credentials = [NSString stringWithFormat: @"%@:%@", usr, pwd]; 
const char* credentialsChars = [credentials cStringUsingEncoding: NSUTF8StringEncoding]; 
credentials = [CommunicationUtil stringBase64WithData: (const UInt8*) credentialsChars length: strlen(credentialsChars)]; 
NSString* authorizationHeader = [NSString stringWithFormat: @"Basic %@", credentials]; 

NSMutableURLRequest* request = 
    [[NSMutableURLRequest alloc] initWithURL: url 
     cachePolicy: NSURLRequestReloadIgnoringLocalCacheData 
     timeoutInterval: 15]; 

    [request setValue: authorizationHeader forHTTPHeaderField: @"Authorization"]; 

Teraz moja aplikacja działa bardzo sprawnie i jest bardzo elastyczny.

Rozwiązanie będzie wyglądać nieco inaczej dla uwierzytelnienia trawienia. Ale wpadniesz na pomysł.

+1

Uwierzytelnianie szyfrowane wygląda * bardzo * inaczej. Jeśli ASIHTTPRequest obsługuje już to, użyłbym tego zamiast fudowania jakiegoś krypto. –

+1

Zgodnie z dokumentami, ASIHTTPRequest ma, więc chciałbym iść z sugestii tc. Oszczędzi ci to wiele bólu od konieczności ręcznego kodowania wszystkich tych rzeczy. –

+0

Sprawdziłem szczegóły uwierzytelniania trawienia i muszę się zgodzić: jestem dość nieporęczny w implementacji. Obliczanie skrótów MD5 jest najłatwiejszą częścią. Obsługa wszystkich szczegółów w nagłówku HTTP jest trudną częścią. Więc tak: prawdopodobnie najlepiej jest wypróbować ASIHTTPRequest. – Codo

Powiązane problemy