Android WebView - with authenticated proxy

2019-03-16 17:44发布

问题:

I am currently trying to debug an Android App built around WebView. The development network environment that I am tasked to deal with (not my choice, it is an 'enterprisey' security decision) is WPA WiFi + proxy server + proxy authentication.

While the instructions on a very helpful previous answer were great, I'm trying to find a way to configure both proxy host:port and username:password.

My constraints are:

  • Phone is not rooted - trying to reproduce a customer-reported bug, would rather not deviate from typical customer setup
  • Running a Samsung Galaxy S on Froyo
  • Built against 2.1

Android apps aren't my usual thing, again not my choice, so if I'm blatantly missing details, be nice ;)

回答1:

See this Related Answer.



回答2:

With WebView android proxy configuration, for basic scheme preemptive proxy authentication,

Starting from Android 2.2, the extra header can be set for authentication. The following can add a header for webView's http request:

    public void loadUrl(WebView view, String url, String proxyUserName, String proxyPassword){
            UsernamePasswordCredentials creds= new UsernamePasswordCredentials(proxyUserName, proxyPassword);
            Header credHeader = BasicScheme.authenticate(creds, "UTF-8", true);
            Map<String, String> header = new HashMap<String, String>();
            header.put(credHeader.getName(), credHeader.getValue());
            view.loadUrl(url, header);
    }

For older version, the preemptive proxy authentication can be set on mProxyUserName and mProxyPassword in android.webkit.Network by reflection:

public void loadUrl(WebView view, String url, String proxyUserName, String proxyPassword){
    try{
        Class networkClass = Class.forName("android.webkit.Network");
        if (networkClass != null) {
            Object networkObj = invokeMethod(networkClass, "getInstance", new Object[]{view.getContext()}, Context.class);
            if (networkObj != null) {
                Field mProxyUserName = obj.getClass().getDeclaredField("mProxyUserName");
                mProxyUserName.setAccessible(true);mProxyUserName.set(networkObj, proxyUserName);
                Field mProxyPassword = obj.getClass().getDeclaredField("mProxyPassword");
                mProxyPassword.setAccessible(true);mProxyPassword.set(networkObj, proxyPassword);                       
            }
        }
    }catch(Exception e){
        e.printStackTrace();
    }
    view.loadUrl(url);
}

When you load a new url, both loadUrl() must need to call again. That is very important. Therefore, a custom WebViewClient should be used to override shouldOverrideUrlLoading(WebView view, String url)

class ProxyAuthWebViewClient extends WebViewClient {
    String proxyUserName;
    String proxyPassword;
    public ProxyAuthWebViewClient(String proxyUserName, String proxyPassword){
        this.proxyUserName = proxyUserName;
        this.proxyPassword = proxyPassword;
    }
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        loadUrl(view, url, proxyUserName, proxyPassword);
        return true ;
    }
}

And set the WebViewClient on your webView:

webView.setWebViewClient(new ProxyAuthWebViewClient("user", "password"));