2016-05-13 30 views
5

Używam Adapter-based authentication in native iOS applications do podłączenia mojej natywnej aplikacji ios (Swift) do serwera Mobilefirst (7.0).Serwer Mobilefirst zwraca błąd 403 po obsłudze limitu czasu sesji w natywnej aplikacji ios

Mechanizm uwierzytelniania działa poprawnie, ale problem pojawia się, gdy sesja wygasa po 10 minutach.

Tutaj można zobaczyć część kodu gdzie obsługiwać uwierzytelnianie i limit czasu sesji:

override func isCustomResponse(response: WLResponse!) -> Bool { 
    if response != nil && response.responseJSON != nil { 
     let responseJson: NSDictionary = response.responseJSON as NSDictionary 
     if responseJson.objectForKey("authRequired") != nil{ 
      return responseJson.objectForKey("authRequired") as! Bool 
     } 
    } 
    return false 
} 

override func handleChallenge(response: WLResponse!) { 

    NSLog("A login form should appear") 

    if self.vc.navigationController?.visibleViewController!.isKindOfClass(LoginViewController) == true { 
     NSLog("Already the login form") 
     dispatch_async(dispatch_get_main_queue()) { 
      let loginController : LoginViewController! = self.vc.navigationController?.visibleViewController as? LoginViewController 

      let myInvocationData = WLProcedureInvocationData(adapterName: "AuthenticationJavaAdapter", procedureName: "authenticate") 
      myInvocationData.parameters = [loginController.userID, loginController.userPass] 
      self.submitAdapterAuthentication(myInvocationData, options: nil) 
     } 
    } else if (self.vc.navigationController?.visibleViewController!.isKindOfClass(SignUpViewController) == true) { 
     NSLog("Already the signup form") 
     dispatch_async(dispatch_get_main_queue()) { 
      NSLog("AuthenticationJavaAdapter") 
      let sigupController : SignUpViewController! = self.vc.navigationController?.visibleViewController as? SignUpViewController 

      let myInvocationData = WLProcedureInvocationData(adapterName: "AuthenticationJavaAdapter", procedureName: "authenticate") 
      myInvocationData.parameters = [sigupController.userID, sigupController.userPass] 
      self.submitAdapterAuthentication(myInvocationData, options: nil) 
     } 
    }else { //TEST 
     NSLog("A login form is not there yet") 
     //After 10 minutes this will execute, it will perform a unwind segue to the login 
     //timeOutController is a global var declared in LoginViewController 
     timeOutController.performSegueWithIdentifier("logOutDueToTimeOut", sender: nil) 
    } 
} 

Kiedy sesja wygasa jest aplikacja w tle, a następnie wraca do nowej wiedzy i wywołuje chroniony adaptera ta część kodu jest wykonywany.

timeOutController.performSegueWithIdentifier("logOutDueToTimeOut", sender: nil) 

login zobacz ładunki z sukcesu i mogę złożyć ponownie poświadczenia, aby zalogować się w problemem jest to, że moja aplikacja nie jest już w stanie uwierzytelnić się na serwerze Mobilefirst, coraz th jest błąd:

[DEBUG] [WL_REQUEST] -[WLRequest requestFinished:] in WLRequest.m:385 :: no token present 
2016-05-13 12:58:29.241 BNNDesignCollection[46327:318014] [DEBUG] [WL_PUSH] -[WLPush updateToken:] in WLPush.m:410 :: Server token is (null) 
.... 
.... 
.... 
2016-05-13 12:58:29.352 BNNDesignCollection[46327:318014] [DEBUG] [WL_AFHTTPCLIENTWRAPPER_PACKAGE] -[WLAFHTTPClientWrapper requestFailed:error:] in WLAFHTTPClientWrapper.m:335 :: Response Status Code : 403 
2016-05-13 12:58:29.352 BNNDesignCollection[46327:318014] [DEBUG] [WL_AFHTTPCLIENTWRAPPER_PACKAGE] -[WLAFHTTPClientWrapper requestFailed:error:] in WLAFHTTPClientWrapper.m:336 :: Response Error : Expected status code in (200-299), got 403 

Wydaje się, że wniosek nie ma żeton lub jest nieprawidłowy, ale nie dostać „authrequired” pole w odpowiedzi JSON tak, że nie może uwierzytelnić znowu jak ja po raz pierwszy aplikacja uwierzytelnia się przed dowolnym limitem czasu sesji Mobilefirst.

Szczegółowe krok po wykonaniu kroku jest to jedno:

  1. Aplikacja pokazuje ekran logowania dla użytkownika
  2. użytkownik wpisze poświadczenia
  3. jako chronionej adapter nazywa się podczas tego procesu Serwer mobilefirst zwraca odpowiedź z "authrequired = true". Metoda isCustomResponse jest automatycznie wywoływana i zwraca wartość true.
  4. Jak isCustomResponse zwraca true, metoda handleChallenge nazywa i jak widać viewController jest loginViewController, pierwszy „if” jest wykonywany, uruchomienie uwierzytelniania.
  5. Uwierzytelnianie uda i teraz użytkownik może poruszać się w całej aplikacji dostęp do wszystkich swoich chronionych zasobów.
  6. Umieszczam aplikację w tle na 10 minut (ustalony limit czasu sesji MobileFirst na serwerze).
  7. Umieszczam aplikację na pierwszym planie i ponownie uruchamiam nawigację.
  8. Gdy sesja MobileFirst wygasła, raz spróbuję ponownie połączyć się z zabezpieczonym adapterem, serwer mobilefirst zwraca odpowiedź z "authrequired = true". Metoda isCustomResponse jest automatycznie wywoływana ponownie i zwraca wartość true.
  9. Jak isCustomResponse zwraca true, metoda handleChallenge nazywa i jak widać viewController NIE jest loginViewController, trzeci „if” jest wykonywany, pokazując ekran logowania ponownie.
  10. Użytkownik wpisuje dane uwierzytelniające.
  11. Serwer zwraca odpowiedź 403. Metoda isCustomResponse jest automatycznie wywoływana, ale zwraca wartość false, ponieważ odpowiedź nie zawiera pola "authquaint".

Wszelkie pomysły, w jaki sposób sobie z tym poradzić?

+0

Skąd wiesz (w kodzie), że sesja wygasła? Napisałeś, że wykonujesz segue, gdy sesja wygasła, ale nie widzę nigdzie w twoim kodzie części, która wykrywa limit czasu. –

+0

Metoda isCustomResponse obsługi wywołania jest wywoływana za każdym razem, gdy odpowiedź jest odbierana z serwera. Jeśli isCustomResponse zwróci true, struktura wywoła metodę handleChallenge i dzieje się tak, gdy w odpowiedzi zostanie wykryte pole "authRequired". Po wygaśnięciu sesji i wywołaniu chronionego adaptera metoda isCustomResponse zwraca wartość true, a metoda handleChallenge jest wykonywana. To wykrywanie działa poprawnie, a ekran logowania ładuje się ponownie.Jednak po ponownym zalogowaniu się serwer worklight nie zwraca ponownie pola "authiredqu", aby ponownie wykonać uwierzytelnianie. –

+0

Przepraszam, wciąż nie rozumiem. "Ale, gdy zalogujesz się ponownie" - co masz na myśli po ponownym zalogowaniu? Jeśli 'isCustomResponse' zwróci true, oznacza to, że otrzymałeś' authrequired' zgodnie z oczekiwaniami. Zaktualizuj swoje pytanie BARDZO SZCZEGÓŁOWĄ krok po kroku, w tym fragmenty kodu. –

Odpowiedz

2

Istnieje kilka problemów, które widzę w procesie uwierzytelniania.

  • Twoje kroki zaczynają się od "Aplikacja pokazuje ekran logowania do użytkownika". Czy programujesz na twardym dysku aplikację, aby rozpocząć od ekranu logowania? Uwierzytelnianie na podstawie adapterów nie obsługuje uwierzytelniania "wyprzedzającego". Znaczenie tylko wyzwanie powinno pokazać ekran logowania. Najczęstszym sposobem jest wywołanie chronionego zasobu podczas uruchamiania aplikacji lub użycie interfejsu API login, aby wywołać wyzwanie. Twój handleChallenge powinien wtedy wyświetlić ekran logowania.
  • "W trakcie tego procesu wywoływany jest chroniony adapter". Wywołujesz chroniony zasób w trakcie przepływu uwierzytelniania. Nie dobrze. Nie rób tego.
  • Twoje handleChallenge automatycznie przesyła dane uwierzytelniające, jeśli kontroler widoku LoginViewController jest już na ekranie. Co się stanie, jeśli użytkownik wprowadzi nieprawidłowe dane uwierzytelniające? Czy nie wyśle ​​złych referencji w pętli? Zwykle, jeśli LoginViewController jest już na ekranie, po prostu chcesz zaktualizować interfejs użytkownika, na przykład "nieprawidłowe dane, spróbuj ponownie".
  • Kliknięcie przycisku "zaloguj się" powinno być tym, co wyzwala submitAdapterAuthentication. Wyzwanie nie powinno wyzwalać submitAdapterAuthentication.
  • Każdemu wyzwaniu przychodzącemu należy odpowiedzieć, zanim zrobisz cokolwiek innego. Oznacza to, że po wywołaniu handleChallenge nie można podejmować żadnych innych chronionych żądań ani wywoływać innych problemów.

Odnośnie konkretnego problemu, to co myślę dzieje się po timeout:

  • handleChallenge nazywa, który otwiera ekran logowania.
  • Napisałeś, że "podczas tego procesu wywoływany jest chroniony adapter", czego nie możesz zrobić, ponieważ jesteś w trakcie wyzwania.
  • Aplikacja przechodzi w stan niestabilny.

Jeśli postąpisz zgodnie z komentarzami, które napisałem powyżej, powinieneś być w porządku. Ale będzie to wymagało pewnych zmian architektonicznych w twojej aplikacji. Ważna jest kolejność zdarzeń:

  1. Złóż wniosek chroniony.
  2. handleChallenge pokazuje formularz logowania.
  3. Użytkownik klika na przesłanie.
  4. submitAdapterAuthentication

To nie ma znaczenia, czy jest to pierwsze uruchomienie, poboru lub po czasie na zewnątrz, upewnij się, że zgodnie z kolejnością operacji.

+0

Bardzo dziękuję za rozwiązanie! Jest naprawdę kompletny, jednak zastanawiając się, jak go wdrożyć, muszę dodać, że nasza aplikacja musi uwierzytelnić się przed zaporą przed uzyskaniem dostępu do serwera MobileFirst, w związku z tym moduł obsługi zgłoszeń nie zostanie nigdy uruchomiony przed uwierzytelnieniem przez tę zaporę, ponieważ serwer Mobilefirst jest dostępne, gdy aplikacja zostanie uwierzytelniona na zaporze. Właśnie dlatego wczytujemy ekran logowania. Wiesz, jak sobie z tym poradzić? –

+0

W jaki sposób uwierzytelnianie działa z zaporą ogniową? Jaki rodzaj uwierzytelnienia? –

+0

Korzysta z podstawowego uwierzytelniania dostępu, więc wysyłamy nazwę użytkownika i hasło w nagłówku –