Skip to content

html 页面中无法展示 https 的图片 #160

@yorkvolvo

Description

@yorkvolvo

问题描述

我在页面中设置 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>

不能正确显示来自服务器的图片:

image

我排查后发现这是 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();
    }
});

问题

  1. 我该如何在 appcan 项目中配置 https 证书呢?

  2. 或者我该如何让我的 appcan 项目里全局请求网络的时候忽略校验证书呢?

PS:项目已整体迁移到 Android Studio 中了。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions