I would like to create an Android Webview that connects to a website via a secured HTTPS
connection with the use of credentials.
First difficulty was to accept the certificate (private), it was solved with this very useful post.
Second difficulty is to use credentials, I found this post.
(first answer from dparnas) which seems to deal pretty well with it, but it talks about HTTP
connection and not HTTPS
. I ve tried it, but it doesnt work, I just reach the sign-in form page without any error message, just the normal blank form.
Here is my code:
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");
}
}
As it seems that WebView
cannot natively handle Basic
authentication when using HTTPS
, I started toying with the idea of setting the Authorization
header (containing the encoded username/password) manually.
Here's how I think this can be done:
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);
}
This takes advantage of the WebView.loadUrl (String url, Map<String, String> additionalHttpHeaders)
method and for this example I'm using the Base64Encoder
from Apache Commons. The Base64Encoder part is quite trivial and if you didn't want to include external libraries in your application (for whatever reason), you could always write your own (reference).
Also note that the aforementioned WebView.loadUrl (String url, Map<String, String> additionalHttpHeaders)
method is only available in API 8+. For reference, see also the Wikipedia article on Basic Authentication (which discusses the headers, etc).