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