Android WebView https与http混合以及跨域问题

1、WebView HTTPS与HTTP混合使用出现的错误

Mixed Content: The page at 'xxx' was loaded over HTTPS, 
but requested an insecure XMLHttpRequest endpoint 'xxxxxxxxx'. 
This request has been blocked; 
the content must be served over HTTPS.", source:xxxxxx

webView加载的htttps网页的内容,但是在html中的js中存在一个http请求,那么加载这个webView的时候出现如上错误;

原因:从Android5.0开始,WebView默认不支持同时加载https与http混合模式

解决:
首先,介绍下这个方法,这个方法我理解的作用是WebView根据开发者设置的模式从安全站点(https)加载非安全站点内容(http)的方式

webView.getSettings().setMixedContentMode(int mode)

WebSettings.MIXED_CONTENT_ALWAYS_ALLOW 这种模式下,WebView是允许一个安全站点(https)去加载另一个非安全站点内容(http),这是WebView最不安全的操作模式,官方文档也不推荐使用;
WebView默认使用WebSettings.MIXED_CONTENT_NEVER_ALLOW这个模式,这种模式下,不允许一个安全站点(https)去加载另一个非安全站点内容(http)。列如我这里出现的情况,WebView加载的htttps网页的内容,但是在html中的js中存在一个http请求就会报错,这里应该加载js中应该加载https请求。我找到前端同事,希望他们这里改一下,但是由于一些原因js里改了https会产生其它问题,他们希望这里支持https与http混合使用

尝试用这个方法去解决我的问题,mode设置成MIXED_CONTENT_ALWAYS_ALLOW

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                webView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
            }

然后发现没效果,在网上找了各种方案都不行,最后重写

WebViewClient 的shouldInterceptRequest(WebView view, WebResourceRequest request)

方法,然后在html中的中添加

<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">

这个html是服务器下发的,读取并重写页面内容,这个解决了问题。

2、WebView 跨域问题

"Access to XMLHttpRequest at 'xxx' from origin 'xxxxxx' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.", source: xxxx

同样重写WebViewClient 的

shouldInterceptRequest(WebView view, WebResourceRequest request)

这个方法,并返回

 new WebResourceResponse(mimeType,"utf-8", 200,"OK",headers,new ByteArrayInputStream(stringBuffer.toString().getBytes()));

mimeType:

MimeTypeMap.getSingleton().getMimeTypeFromExtension(MimeTypeMap.getFileExtensionFromUrl(url));

headers:

Map headers =new HashMap<>();
// 解决webView跨域问题
headers.put("Access-Control-Allow-Origin", xxxxxx);
headers.put("Access-Control-Allow-Headers","X-Requested-With");
headers.put("Access-Control-Allow-Methods","POST, GET, OPTIONS, DELETE");
headers.put("Access-Control-Allow-Credentials", "true");

完整代码:

private WebResourceResponse getWebView(String path){
            WebResourceResponse response = null;
            StringBuffer stringBuffer = new StringBuffer();
            BufferedReader bufferedReader = null;
            try {
                URL url = new URL(path);
                HttpsURLConnection connection = null;
                connection = (HttpsURLConnection) url.openConnection();
                ((HttpsURLConnection) connection).setHostnameVerifier(new HostnameVerifier() {
                    @Override
                    public boolean verify(String hostname, SSLSession session) {
                        return true;
                    }
                });
                connection.setConnectTimeout(10*1000);
                connection.setReadTimeout(10*1000);
                bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                String line = "";
                while ((line = bufferedReader.readLine()) != null){
                    stringBuffer.append(line);
                    if (line.equals("<head>")){
                        // 在<head>中添加<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
                        stringBuffer.append("<meta http-equiv=\"Content-Security-Policy\" content=\"upgrade-insecure-requests\">");
                    }
                }
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                if (bufferedReader != null){
                    try {
                        bufferedReader.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(MimeTypeMap.getFileExtensionFromUrl(path));
            Map<String, String> headers = new HashMap<>();
            // 解决webView跨域问题
            headers.put("Access-Control-Allow-Origin", xxxxxx);
            headers.put("Access-Control-Allow-Headers","X-Requested-With");
            headers.put("Access-Control-Allow-Methods","POST, GET, OPTIONS, DELETE");
            headers.put("Access-Control-Allow-Credentials", "true");

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                response = new WebResourceResponse(mimeType,
                        "utf-8", 200,"OK",headers,
                        new ByteArrayInputStream(stringBuffer.toString().getBytes()));
            }
            return response;
        }
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Android提供了WebView控件来加载和显示Web页面。在使用WebView加载HTTPS网页时,SSL(即Secure Sockets Layer)是必需的。 SSL是一种用于在Internet上保护数据传输安全的加密协议。它确保在浏览器和服务器之间传输的数据是加密的,以防止第三方篡改或窃听数据。 要在Android WebView中使用SSL,需要采取以下步骤: 1. 配置WebView设置:在代码中,我们可以通过设置WebView的WebSettings对象来启用JavaScript和SSL,以便加载HTTPS网页。可以使用以下代码进行设置: ``` WebView webView = findViewById(R.id.webview); WebSettings webSettings = webView.getSettings(); webSettings.setJavaScriptEnabled(true); webSettings.setDomStorageEnabled(true); webSettings.setAppCacheEnabled(true); webSettings.setCacheMode(WebSettings.LOAD_DEFAULT); ``` 2. 导入SSL证书:有时候,我们需要导入服务器的SSL证书,以便WebView可以信任该服务器。可以使用以下代码导入SSL证书: ``` InputStream inputStream = getAssets().open("ssl_cert.cer"); CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); X509Certificate x509Certificate = (X509Certificate) certificateFactory.generateCertificate(inputStream); inputStream.close(); KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); keyStore.load(null, null); keyStore.setCertificateEntry("ssl_cert", x509Certificate); String defaultAlgorithm = KeyManagerFactory.getDefaultAlgorithm(); KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(defaultAlgorithm); keyManagerFactory.init(keyStore, null); TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(defaultAlgorithm); trustManagerFactory.init(keyStore); SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, trustManagerFactory.getTrustManagers(), null); SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); webSettings.setJavaScriptCanOpenWindowsAutomatically(true); webSettings.setUseWideViewPort(true); webSettings.setBuiltInZoomControls(true); webSettings.setDisplayZoomControls(false); webSettings.setSupportZoom(true); webSettings.setAllowFileAccess(true); webSettings.setAllowContentAccess(true); webView.setWebViewClient(new WebViewClient()); webView.getSettings().setJavaScriptEnabled(true); webView.loadUrl("https://www.example.com"); ``` 通过以上步骤,我们就可以在Android WebView中加载HTTPS安全网页并保持通信的安全性。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值