2015-08-17 7 views
25

Ho un backend ASP.NET MVC/Web dove ho implementato un'autenticazione basata su form per la mia app per PhoneGap. L'accesso viene eseguito con l'invio delle credenziali degli utenti tramite jQuery Ajax chiamata in questo modo:Problemi con l'autenticazione di moduli ASP.NET su PhoneGap (Android)

$.ajax({ 
    type: "POST", 
    url: "/api/authentication/login", 
    data: JSON.stringify({ Username: username, Password: password }), 
    contentType: "application/json; charset=utf-8", 
    dataType: "TEXT", 
    statusCode: { 
     200: function (response, status, xhr) { 
      // successfully authenticated 
      Backbone.history.navigate("/", { trigger: true }); 
     } 
    } 
}); 

I backend login metodo è simile al seguente:

[ActionName("login")] 
[AllowAnonymous] 
public LoginResult Login(LoginCredentials credentials) 
{ 
    // doing all kinds of things here 

    // if valid credentials 
    FormsAuthentication.SetAuthCookie(loginID, true); 
    return loginResult; 
} 

ho questo nel mio web.config:

<authentication mode="Forms"> 
    <forms 
    name=".ASPXAUTH" 
    loginUrl="/login" 
    defaultUrl="/home" 
    protection="All" 
    slidingExpiration="true" 
    timeout="525600" 
    cookieless="UseCookies" 
    enableCrossAppRedirects="false" 
    requireSSL="true" 
    > 
    </forms> 
</authentication> 

Ora il problema con Android qui è che il cookie è impostato correttamente e funziona sui miei metodi autorizzati dopo il login, ma a volte (spesso) quando chiudo l'app e lo apro di nuovo, non lo sono onger loggato. Il cookie non c'è più, non riesco a vederlo nella richiesta. Ciò non dovrebbe accadere perché ho impostato il timeout su 525600. Ho notato che questo problema si verifica spesso quando chiudo l'app subito dopo l'accesso. D'altra parte se mi disconnetto e quindi accedi senza chiudere l'app, il cookie viene salvato correttamente.

Tuttavia, se il cookie rimane attivo, la maggior parte delle volte il logout si comporta in modo strano. Questo è come lo faccio la richiesta di disconnessione:

$.ajax({ 
    type: "POST", 
    url: "/api/authentication/logout", 
    data: "{}", 
    contentType: "application/json; charset=utf-8", 
    dataType: "text" 
    success: function (response) { 
     // successfully logged out 
     Backbone.history.navigate("api/login", { trigger: true }); 
    } 
}); 

Il backend:

[ActionName("logout")] 
[AllowAnonymous] 
public String Logout() 
{ 
    FormsAuthentication.SignOut(); 

    HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, ""); 
    cookie.Expires = DateTime.Now.AddYears(-1); 
    HttpContext.Current.Response.Cookies.Add(cookie); 

    return "home"; 
} 

Ora simile al problema con il login, logout sembra prima di avere successo e il cookie non viene inviato con eventuali richieste. Ma quando chiudo l'app e la riapre, il cookie è tornato e ho effettuato nuovamente l'accesso. Vedo che il cookie ha lo stesso valore di quello che pensavo di aver rimosso impostando la sua data di scadenza sul passato.

Ho provato tutti i tipi di trucchi, come:

  • ricarica in più dopo il login/logout (location.reload())
  • esecuzione logout/richiesta di login più volte
  • esecuzione richiesta ad altri metodi dopo il login/logout
  • 1-10 secondi di timeout tra la richiesta di accesso/uscita e la ricarica
  • tutti i tipi di variazioni sopra

L'autenticazione funziona come previsto su iOS e Windows Phone. Il problema si verifica solo su Android (testato su KitKat e Lollipop). Nessun problema con l'emulatore Android, ma su dispositivi reali e l'emulatore Android Visual Studios succede sempre.

Non so in che direzione andare da qui. C'è qualcosa in Android WebView che potrebbe causare questo tipo di comportamento? C'è qualcos'altro che potrei provare? Per favore aiuto!

Sono più che felice di fornire ulteriori informazioni se necessario.

EDIT: Ispirato dal commento di Fabian, ho cambiato il metodo logout per questo:

FormsAuthentication.SignOut(); 

HttpCookie cookie = HttpContext.Current.Response.Cookies[FormsAuthentication.FormsCookieName]; 
cookie.Expires = DateTime.Now.AddYears(-1); 
HttpContext.Current.Response.Cookies.Clear(); 
HttpContext.Current.Response.Cookies.Add(cookie); 

return "home"; 

Invece di creare un nuovo cookie, ho usato quella nella risposta. Non ha funzionato.

Ho anche provato qualcosa che ho trovato da qui: http://techblog.dorogin.com/2013/01/formsauthentication-gotcha-with-signout.html Anche questo non ha fatto differenza, il percorso non era il problema. Sto ancora cercando una soluzione.

UN ALTRE MODIFICHE: Ancora non è possibile trovare una soluzione per questo. Ho dovuto fare una soluzione orribile.

  • accesso: faccio due ricariche dopo il login e poi la richiesta di un metodo fittizio. Questo sembra funzionare ogni volta.
  • Esci: Uso una bandiera posizionata in localStorage per determinare se l'utente si è disconnesso ed eseguire un logout all'avvio. Questo rimuove sempre il cookie correttamente.

Non sono soddisfatto di questi hack e spero ancora in una soluzione migliore.

+0

penso che si dovrebbe pubblicare il tuo codice di Android per ulteriori informazioni. – BNK

+0

Cosa intendi con "codice Android"? Sto parlando di un'applicazione PhoneGap e tutto il relativo codice JS è nella domanda. – balzafin

+0

Significo che come impostate la vostra WebView – BNK

risposta

1

PhoneGap carica i file dal protocollo file://. Sfortunatamente, non sono consentite richieste di attraversamento dell'origine e, a meno che non si aprano richieste di origine incrociata da tutti gli host *, questo problema non verrà risolto.

Ci sono molti modi per risolvere questo problema, ma sono davvero lunghi.

carico Html da http://

carico intero sito web dal server web invece di storage locale. Ciò rimuove tutti i problemi con richieste di origine incrociata. Il vantaggio è che non è necessario pubblicare una nuova versione dell'app quando si cambia l'interfaccia utente. Ma dovrai implementare il caching molto potente e l'app per la prima volta richiederà più tempo.

Intercept http:// e fornire i file locali

Come sapete, PhoneGap usa semplicemente WebView, in tutte le piattaforme, si può semplicemente ignorare protocollo URL per iniettare i file dall'archivio locale della tua applicazione. Questo sarà più veloce, e il browser penserà che sta caricando html dalla stessa risorsa.

Setup OAuth + intestazione personalizzata per l'autenticazione

  1. reindirizzamento ad una pagina di login ospitata al tuo sito web dire http://domain.com/api/login
  2. Dopo l'accesso, utilizzare PhoneGap localStorage (non localStorage del browser) per memorizzare l'autorizzazione.
  3. Passare alle pagine html locali dall'app e per ogni richiesta di json api da inviare al server, inviare l'intestazione di autorizzazione come intestazione separata in una richiesta Ajax.
  4. Setup un modulo di autorizzazione, in cui è possibile autorizzare manualmente richiesta asp.net se la vostra autorizzazione è stata inviata tramite header personalizzato in richiesta http
+0

Grazie per la risposta dettagliata. Penso che tu abbia ragione, il modo corretto per risolvere questo è cambiare il metodo di autenticazione in OAuth o simile. – balzafin

0

Secondo MSDN:

Il metodo FormsAuthentication.SignOut rimuove le informazioni biglietto forme-autenticazione dal cookie.

E questo è tutto ciò che serve per disconnettere l'utente. Non è necessario scadere o rimuovere il cookie stesso. Basta cambiare la tua Logout() a:

[ActionName("logout")] 
[AllowAnonymous] 
public String Logout() 
{ 
    FormsAuthentication.SignOut(); 
    return "home"; 
} 
1

credo di aver trovato la soluzione. La versione di PhoneGap sul file config.xml è cli-5.1.1, che include la versione di Android Phone Phone 4.0.2 in base allo documentation.

Il problema con le versioni è che il team Android PhoneGap ha risolto il problema di archiviazione dei cookie sulla versione 5.2.0. Si può trovare in release notes come:

CB-10896 abbiamo mai attivato i cookie sul WebView corretta

Pertanto, l'aggiornamento del PhoneGap all'ultima versione dovrebbe risolvere il problema.

+0

Dove hai trovato il file config.xml di OP? – MarioDS

+0

Non credo di avere la domanda. Potresti essere più specifico? –

+0

Purtroppo questo non ha risolto il problema. Sto usando cli-6.3.0 (Android 5.2.1) ora e il login/logout si comporta esattamente allo stesso modo. – balzafin