最近的项目里,有了这样的需求,需要预览图片。正常的理解觉得只要在后台处理好,直接把img标签在前台表示就可以,谁知道并不是想象中的那么简单。
当img标签的src属性指向https站点的时候问题来了,后来加入了如下处理,才解决了这个问题。具体的原因是因为安全证书的问题。
URL url = new URL(imageUrl);
System.setProperty("java.protocol.handler.pkgs", "javax.net.ssl");
HostnameVerifier hv = new HostnameVerifier() {
public boolean verify(String urlHostName, SSLSession session) {
return urlHostName.equals(session.getPeerHost());
}
};
HttpsURLConnection.setDefaultHostnameVerifier(hv);
TrustManager[] tm = { new CustomX509TrustManager() };
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
sslContext.init(null, tm, new java.security.SecureRandom());
SSLSocketFactory ssf = sslContext.getSocketFactory();
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setSSLSocketFactory(ssf);
input = new DataInputStream(conn.getInputStream());
用到的CustomX509TrustManager 代码如下
import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
public class CustomX509TrustManager implements X509TrustManager {
/*
* The default X509TrustManager returned by SunX509. We'll delegate
* decisions to it, and fall back to the logic in this class if the default
* X509TrustManager doesn't trust it.
*/
X509TrustManager sunJSSEX509TrustManager;
public CustomX509TrustManager() throws Exception {
// create a "default" JSSE X509TrustManager.
KeyStore ks = KeyStore.getInstance("JKS");
//ks.load(new FileInputStream("trustedCerts"), "passphrase".toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509","SunJSSE");
tmf.init(ks);
TrustManager tms[] = tmf.getTrustManagers();
/*
* Iterate over the returned trustmanagers, look for an instance of
* X509TrustManager. If found, use that as our "default" trust manager.
*/
for (int i = 0; i < tms.length; i++) {
if (tms[i] instanceof X509TrustManager) {
sunJSSEX509TrustManager = (X509TrustManager) tms[i];
return;
}
}
/*
* Find some other way to initialize, or else we have to fail the
* constructor.
*/
throw new Exception("init failure");
}
/*
* Delegate to the default trust manager.
*/
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
try {
sunJSSEX509TrustManager.checkClientTrusted(chain, authType);
} catch (CertificateException excep) {
// do any special handling here, or rethrow exception.
}
}
/*
* Delegate to the default trust manager.
*/
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
try {
sunJSSEX509TrustManager.checkServerTrusted(chain, authType);
} catch (CertificateException excep) {
/*
* Possibly pop up a dialog box asking whether to trust the cert
* chain.
*/
//excep.printStackTrace();
}
}
/*
* Merely pass this through.
*/
public X509Certificate[] getAcceptedIssuers() {
return sunJSSEX509TrustManager.getAcceptedIssuers();
}
}