2010-12-27 11 views
13

Me gustaría crear una vista web de Android que se conecte a un sitio web a través de una conexión segura HTTPS con el uso de credenciales.Establecer credenciales en una vista web de Android mediante conexión HTTPS segura

La primera dificultad fue aceptar el certificado (privado), se resolvió con this publicación muy útil.

La segunda dificultad es usar credenciales, encontré this mensaje.

(primera respuesta de dparnas) que parece tratar bastante bien con ella, pero habla de la conexión HTTP y no de HTTPS. Lo probé, pero no funciona, acabo de llegar a la página de formulario de inicio de sesión sin ningún mensaje de error, solo el formulario en blanco normal.

Aquí está mi código:

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"); 
    } 
} 

Respuesta

3

La clase WebView no proporciona tanta flexibilidad en su conectividad como el uso de las clases de bajo nivel (como HttpPost o similares) directamente.

Si necesita controlar completamente la conexión al servidor - o manejar escenarios de autorización complicados como este - use las clases de bajo nivel, recupere los datos, luego use WebView.loadData() para cargar y mostrar el HTML.

Here es un buen ejemplo de carga de contenido utilizando SSL y BasicCredentialProvider. El resultado de esto podría cargarse en WebView como se describe arriba.

+0

Parece que no va a haber más respuestas, así que le otorgaré la recompensa.No tiene sentido perderlo :) –

+0

"complicados escenarios de autorización" jajajajaja, este es un RFC completamente estándar de hace años, webview debería manejar esto ... – Nappy

+0

mientras yo estoy de acuerdo que "debería" - ¡y desearía que lo hiciera! - webview solo expone un cierto subconjunto del comportamiento que admite la biblioteca HTTP completa ... – elijah

13

Como parece que WebView no puede manejar de forma nativa Basic autenticación cuando se utiliza HTTPS, empecé a jugar con la idea de crear la cabecera Authorization (que contiene el nombre de usuario/contraseña codificada) manualmente.

Así es como creo que esto se puede hacer:

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); 
} 

Esto toma ventaja del método WebView.loadUrl (String url, Map<String, String> additionalHttpHeaders) y para este ejemplo estoy usando el Base64Encoder de Apache Commons. La parte de Base64Encoder es bastante trivial y si no desea incluir bibliotecas externas en su aplicación (por cualquier razón), siempre puede escribir su own (reference).

También tenga en cuenta que el método WebView.loadUrl (String url, Map<String, String> additionalHttpHeaders) antes mencionado solo está disponible en API 8+. Para referencia, vea también el artículo de Wikipedia en Basic Authentication (que discute los encabezados, etc.).

+0

¡Gran solución! En mi caso, implementé en el formulario de inicio de sesión automático del servidor, cuando el usuario no es reconocido, por lo que la solución con webviewclient no funcionaba, ¡pero el mapa de encabezados funcionaba bien! ¡Gracias! – Krystian

0

Escenario alternativo:

Si dispuestos a escribir roundabout 10 lines of javascript using jQuery, este escenario es bastante simple.

Inject your javascript code into the webview o en el caso de que esté controlando la página html que está visualizando, inclúyalo allí.

Si necesita interface back from javascript, puede hacerlo. Para un intercambio de comandos más pesado, use CordovaWebView -Interfaz que tiene un retraso menor dependiendo del nivel de la API.

Cuestiones relacionadas