使用安全的 HTTPS 连接在 Android Webview 上设置凭据

IT小君   2022-01-11T05:15:12

我想创建一个 Android Webview,它HTTPS使用凭据通过安全连接连接到网站

第一个困难是接受证书(私人),这个非常有用的帖子解决了

第二个困难是使用凭据,我找到了这篇文章。

(来自 dparnas 的第一个回答)这似乎处理得很好,但它谈论的是HTTPconnection 而不是HTTPS. 我试过了,但它不起作用,我只是进入登录表单页面,没有任何错误消息,只是正常的空白表单。

这是我的代码:

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");
  }
}
评论(3)
IT小君

由于使用时似乎WebView无法原生处理Basic身份验证HTTPS,我开始尝试Authorization手动设置标头(包含编码的用户名/密码)的想法

以下是我认为可以做到的方式:

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

这利用了该WebView.loadUrl (String url, Map<String, String> additionalHttpHeaders)方法,对于此示例,我使用的是Base64Encoder来自Apache Commons 的方法Base64Encoder 部分非常简单,如果您不想在应用程序中包含外部库(无论出于何种原因),您总是可以编写自己的参考)。

另请注意,上述WebView.loadUrl (String url, Map<String, String> additionalHttpHeaders)方法仅适用于 API 8+。作为参考,另请参阅有关基本身份验证的 Wikipedia 文章(其中讨论了标头等)。

2022-01-11T05:15:12   回复
IT小君

WebView 类在连接性方面没有提供像直接使用低级类(例如 HttpPost 等)那样的灵活性。

如果您需要完全控制与服务器的连接——或者处理复杂的授权场景,比如这个——使用低级类,检索数据,然后使用 WebView.loadData() 加载和显示 HTML。

是使用 SSL 和 BasicCredentialProvider 加载内容的一个很好的示例。如上所述,此结果可以加载到 WebView 中。

2022-01-11T05:15:12   回复
IT小君

替代方案

如果愿意使用 jQuery编写10 行左右的 javascript,那么这个场景是相当简单的。

将您的 javascript 代码注入到 webview 中,或者如果您正在控制正在显示的 html 页面,请将其包含在其中。

如果您需要从 javascript 接口返回,您可以这样做。对于较重的命令交换,请使用CordovaWebView-Interface,它根据 api 级别具有较低的延迟。

2022-01-11T05:15:12   回复