html 页面中无法展示 https 的图片
yorkvolvo opened this issue · comments
问题描述
我在页面中设置 img
src
属性的时候,如果图片设置成我们服务器的 https
链接,那么图片就不会显示。代码:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>Title Here</title>
<script type="text/javascript"></script>
</head>
<body>
<div class="uwh-bg umar-r-ect uwh-bg-img" id="imgtest">
<img class="upimg" id="imgtesta" src="https://172.28.1.209/image......" width="100px" height="100px"/>
</div>
</body>
</html>
不能正确显示来自服务器的图片:
我排查后发现这是 https 证书配置问题,错误日志:
I/X509Util: Failed to validate the certificate chain, error: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
页面中的 https
请求都是没问题的:
appcan.ajax({
type:"POST",
url:baseUrl+url,
data:data
offline:false,
expire:1000,
timeout : 30000,
dataType: 'json',
beforeSend:function(xhr){
},
success:function(ret,status,xhr){
},
error:function(xhr,type){
}
});
尝试的解决办法
我试着在修改引擎代码,不要去做证书校验,在 org.zywx.wbpalmstar.platform.certificates.Http
中忽略证书校验:
public class Http {
public static HashMap<String, KeyStore> KEY_STORE = new HashMap<String, KeyStore>();
public static String algorithm = "X509";
public static String keyType = "pkcs12";
/**
* 是否检查https证书为可信机构颁发
*/
private static boolean isCheckTrustCert = false;
private static InputStream getInputStream(String cPath, Context ctx)
throws IOException, FileNotFoundException {
InputStream inStream;
String assertFile = "file:///android_asset/";
String sdcardFile = "/sdcard/";
String wgtFile = "widget/";
String file = "file://";
if (cPath.contains(assertFile)) {
cPath = cPath.substring(assertFile.length());
AssetManager asset = ctx.getAssets();
inStream = asset.open(cPath);
} else if (cPath.contains(sdcardFile)) {
if (cPath.contains(file)) {
cPath = cPath.substring("file://".length());
}
inStream = new FileInputStream(cPath);
} else if (cPath.startsWith(wgtFile)) {
AssetManager asset = ctx.getAssets();
inStream = asset.open(cPath);
} else {
inStream = new FileInputStream(cPath);
}
return inStream;
}
public static javax.net.ssl.SSLSocketFactory getSSLSocketFactoryWithCert(String cPassWord, String cPath, Context ctx) {
Log.e("httptest", "httptest == getSSLSocketFactoryWithCert(String cPassWord, String cPath, Context ctx)");
SSLContext sslContext = null;
try {
sslContext = SSLContext.getInstance("SSL");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
TrustManager[] tm = {new HX509TrustManager()};
try {
sslContext.init(null, tm, new java.security.SecureRandom());
} catch (KeyManagementException e) {
e.printStackTrace();
}
return sslContext.getSocketFactory();
}
public static javax.net.ssl.SSLSocketFactory getSSLSocketFactory() {
Log.e("httptest", "httptest == getSSLSocketFactory()");
SSLContext sslContext = null;
try {
sslContext = SSLContext.getInstance("SSL");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
TrustManager[] tm = {new HX509TrustManager()};
try {
sslContext.init(null, tm, new java.security.SecureRandom());
} catch (KeyManagementException e) {
e.printStackTrace();
}
return sslContext.getSocketFactory();
}
public static HttpsURLConnection getHttpsURLConnection(URL url) throws Exception {
Log.e("httptest", "httptest == getHttpsURLConnection(URL url)");
HttpsURLConnection mConnection = null;
mConnection = (HttpsURLConnection) url.openConnection();
javax.net.ssl.SSLSocketFactory ssFact = null;
ssFact = Http.getSSLSocketFactory();
((HttpsURLConnection) mConnection).setSSLSocketFactory(ssFact);
if (!isCheckTrustCert()) {
((HttpsURLConnection) mConnection)
.setHostnameVerifier(new HX509HostnameVerifier());
} else {
((HttpsURLConnection) mConnection)
.setHostnameVerifier(new HX509HostnameVerifier());
}
return mConnection;
}
public static HttpsURLConnection getHttpsURLConnection(String urlString) throws Exception {
URL url=new URL(urlString);
HttpsURLConnection mConnection = getHttpsURLConnection(url);
return mConnection;
}
public static HttpsURLConnection getHttpsURLConnectionWithCert(URL url,
String cPassWord, String cPath, Context ctx) throws Exception {
HttpsURLConnection mConnection = null;
mConnection = (HttpsURLConnection) url.openConnection();
javax.net.ssl.SSLSocketFactory ssFact = null;
ssFact = Http.getSSLSocketFactoryWithCert(cPassWord, cPath, ctx);
((HttpsURLConnection) mConnection).setSSLSocketFactory(ssFact);
if (!isCheckTrustCert()) {
((HttpsURLConnection) mConnection)
.setHostnameVerifier(new HX509HostnameVerifier());
} else {
((HttpsURLConnection) mConnection)
.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
}
return mConnection;
}
public static boolean isCheckTrustCert() {
return isCheckTrustCert;
}
public static void setCheckTrustCert(boolean isCheckTrustCert) {
Http.isCheckTrustCert = isCheckTrustCert;
}
}
但是这并没有解决我们的问题,我在网上搜索之后发现 appcan 类似的问题:https自定义证书如何能通过安全认证,但是也是一直没有解决。
可能的解决方案
网上搜索发现在 onReceivedSslError
方法中接受证书就可以解决问题。
webView.setWebViewClient(new WebViewClient() {
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error){
handler.proceed();
}
});
问题
-
我该如何在
appcan
项目中配置https
证书呢? -
或者我该如何让我的
appcan
项目里全局请求网络的时候忽略校验证书呢?
PS:项目已整体迁移到 Android Studio
中了。
@sandy1108 , 能帮忙看下这个 issue 吗?
@sandy1108 , 能帮忙看下这个 issue 吗?
你的问题说的可真详细啊。你说的里面不是写了吗,onReceivedSslError这个方法改写一下就可以了。忽略证书校验后,对于一些安全检测的机构来说,这是不安全的。所以可能没有把这个代码合并到主干中。