2010-12-27 4 views
13

Chciałbym utworzyć widok internetowy Android, który łączy się z witryną poprzez bezpieczne połączenie HTTPS przy użyciu poświadczeń.Ustaw poświadczenia w widoku internetowym systemu Android za pomocą bezpiecznego połączenia HTTPS

Pierwsza trudność polegała na zaakceptowaniu certyfikatu (prywatny), został on rozwiązany dzięki bardzo przydatnemu wpisowi w postaci this.

Druga trudność polega na użyciu poświadczeń, znalazłem post this.

(pierwsza odpowiedź od dparnas), która wydaje się dobrze z nim radzić, ale mówi o połączeniu HTTP, a nie HTTPS. Próbowałem, ale to nie działa, po prostu osiągam stronę formularza logowania bez żadnego komunikatu o błędzie, tylko normalny pusty formularz.

Oto mój kod:

import android.app.Activity; 
import android.net.http.SslError; 
import android.os.Bundle; 
import android.webkit.HttpAuthHandler; 
import android.webkit.SslErrorHandler; 
import android.webkit.WebView; 
import android.webkit.WebViewClient; 

public class ConnectorWebView extends Activity { 
    WebView mWebView; 
    String mUsrName; 
    String mPassC; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.connwebview); 

    // Getting info from Intent extras 
    // Get it if it s different from null 
    Bundle extras = getIntent().getExtras();    
    mUsrName = extras != null ? extras.getString("username") : null; 
    mPassC = extras != null ? extras.getString("passcode") : null; 

    mWebView = (WebView) findViewById(R.id.webview); 
    mWebView.getSettings().setJavaScriptEnabled(true); 
    mWebView.setHttpAuthUsernamePassword("myhost.com", "myrealm", mUsrName, mPassC); 

    mWebView.setWebViewClient(new WebViewClient() { 
     @Override 
     public void onReceivedHttpAuthRequest (WebView view, HttpAuthHandler handler, String host, String realm){ 
      handler.proceed(mUsrName, mPassC); 
     } 

     public void onReceivedSslError (WebView view, SslErrorHandler handler, SslError error) { 
      handler.proceed() ; 
     } 
     }); 

    mWebView.loadUrl("https://myhost.com/secured_area"); 
    } 
} 

Odpowiedz

3

Klasa WebView nie daje tyle elastyczność w jego łączności, jak przy użyciu klas niskim poziomie (takie jak HttpPost lub podobne) bezpośrednio.

Jeśli chcesz w pełni kontrolować połączenie z serwerem - lub radzić sobie ze skomplikowanymi scenariuszami autoryzacji, takimi jak ten - użyj klas niskiego poziomu, pobierz dane, a następnie użyj WebView.loadData(), aby załadować i pokazać HTML.

Here to dobry przykład ładowania treści za pomocą SSL i BasicCredentialProvider. Wynik tego może być załadowany do WebView, jak opisano powyżej.

+0

Nie wygląda na to, że będą jeszcze jakieś odpowiedzi, więc zamierzam przyznać ci nagrodę.Nie ma sensu go tracić :) –

+0

"Skomplikowane scenariusze autoryzacji" hahahahhah, to jest całkowicie standardowe RFC sprzed lat, przeglądanie powinno obsłużyć to ... – Nappy

+0

, podczas gdy ja zgadzam się z tym "powinienem" - i żałuję, że tak! - tylko przeglądarka udostępnia pewien podzbiór zachowań, które obsługuje pełna biblioteka HTTP ... – elijah

13

Jak się wydaje, że WebView nie może natywnie obsługiwać uwierzytelnianie Basic podczas korzystania HTTPS zacząłem toying z ideą ustawienie nagłówka Authorization (zawierający zakodowaną nazwę użytkownika/hasło) ręcznie.

Oto, jak myślę, że można to zrobić:

import org.apache.commons.codec.binary.Base64; 

// ... 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.connwebview); 

    // Getting info from Intent extras 
    // Get it if it s different from null 
    Bundle extras = getIntent().getExtras();    
    mUsrName = extras != null ? extras.getString("username") : null; 
    mPassC = extras != null ? extras.getString("passcode") : null; 

    mWebView = (WebView) findViewById(R.id.webview); 
    mWebView.getSettings().setJavaScriptEnabled(true); 
    // mWebView.setHttpAuthUsernamePassword("myhost.com", 
    //         "myrealm", 
    //         mUsrName, 
    //         mPassC); 

    mWebView.setWebViewClient(new WebViewClient() { 
     @Override 
     public void onReceivedHttpAuthRequest(WebView view, 
              HttpAuthHandler handler, 
              String host, 
              String realm){ 
     handler.proceed(mUsrName, mPassC); 
     } 

     public void onReceivedSslError(WebView view, 
            SslErrorHandler handler, 
            SslError error) { 
     handler.proceed() ; 
     } 
    }); 

    String up = mUserName +":" +mPassC; 
    String authEncoded = new String(Base64.encodeBase64(up.getBytes())); 
    String authHeader = "Basic " +authEncoded; 
    Map<String, String> headers = new HashMap<String, String>(); 
    headers.put("Authorization", authHeader); 
    mWebView.loadUrl("https://myhost.com/secured_area", headers); 
} 

ten wykorzystuje metodę WebView.loadUrl (String url, Map<String, String> additionalHttpHeaders) i na tym przykładzie używam Base64Encoder z Apache Commons. Część Base64Encoder jest dość trywialna i jeśli nie chcesz dołączać zewnętrznych bibliotek do swojej aplikacji (z jakiegokolwiek powodu), zawsze możesz napisać swoją own (reference).

Należy również zauważyć, że wspomniana metoda WebView.loadUrl (String url, Map<String, String> additionalHttpHeaders) jest dostępna tylko w API 8+. Dla odniesienia, zobacz także artykuł w Wikipedii na Basic Authentication (który omawia nagłówki, itp.).

+0

Świetne rozwiązanie! W moim przypadku zaimplementowałem na serwerze automatyczny formularz logowania, gdy użytkownik nie jest rozpoznawany, więc rozwiązanie z webviewclient nie działa, ale mapa nagłówków działa dobrze! Dzięki! – Krystian

0

Scenariusz alternatywny:

Jeśli skłonny napisać roundabout 10 lines of javascript using jQuery, scenariusz ten jest raczej prosty.

Inject your javascript code into the webview lub w przypadku, gdy kontrolujesz wyświetlaną stronę HTML, umieść ją tam.

Jeśli potrzebujesz interface back from javascript, możesz to zrobić. Aby uzyskać cięższą wymianę poleceń, należy użyć interfejsu, który ma niższe opóźnienie w zależności od poziomu interfejsu API.

Powiązane problemy