问题报错具体内容:javax.net.ssl.SSLKeyException: FATAL Alert:BAD_CERTIFICATE - A corrupt or unuseable certificate was received。
背景描述:本地开发环境应用服务器为tomcat,测试环境和生产环境服务器均为weblogic服务器,由于请求的是https协议,并且对方不提供证书。在上普通开发上测试环境后请求收不到返回结果,考虑到是https请求,在没有证书的情况下要是用代码掉过证书校验(具体代码详见 跳过https协议的代码),解决了测试环境的问题;但是在上生产时报了标题中的内容,解决方法见weblogic配置。但是为什么测试环境没有出现该问题呢,后来发现生产和测试配置环境是不一致的。
跳过https协议的代码: import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import org.apache.commons.io.IOUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import net.sf.json.JSONObject; public class SslTest { ?? ?private final static Log log = LogFactory.getLog(SslTest.class); ?? ?/** ?? ? * 忽略https协议,进行查询 ?? ? * @param url ?? ? * @param timeOut ?? ? * @return ?? ? * @author yanh.zhang ?? ? * @throws Exception ?? ? */ ? ? public String getRequest(String url,int timeOut){ ? ? ? ? HttpURLConnection conn = null; ? ? ? ? InputStream inputStream = null; ? ? ? ? String result = ""; ? ? ? ? int responseCode =200; ? ? ? ? try { ? ? ? ? ?? ? URL u = new URL(url); ? ? ? ? ? ? ?if("https".equalsIgnoreCase(u.getProtocol())){ ? ? ? ? ? ? ? ? ?SslUtils.ignoreSsl(); ? ? ? ? ? ? ?} ? ? ? ? ? ? ?conn = (HttpURLConnection) u.openConnection(); ? ? ? ? ?? ? SslUtils.trustAllCertificates(conn); ? ? ? ? ?? ? conn.setDoOutput(true); ? ? ? ? ?? ? conn.setDoInput(true); ? ? ? ? ?? ? conn.setRequestMethod("POST"); ? ? ? ? ?? ? conn.setUseCaches(false); ? ? ? ? ?? ? conn.setRequestProperty("Content-Type", "application/json"); ? ? ? ? ?? ? conn.connect(); ? ? ? ? ?? ? conn.setConnectTimeout(timeOut); ? ? ? ? ?? ? conn.setReadTimeout(timeOut); ? ? ? ? ?? ? conn = (HttpURLConnection) u.openConnection(); ? ? ? ? ? ? responseCode = conn.getResponseCode(); ? ? ? ? ? ? if(responseCode==200) { ? ? ? ? ? ? ?? ?BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8")); ? ? ?? ??? ??? ?StringBuilder sb2 = new StringBuilder(); ? ? ?? ??? ??? ?for (String line = reader.readLine(); line != null; line = reader.readLine()) { ? ? ?? ??? ??? ??? ?sb2.append(line); ? ? ?? ??? ??? ?} ? ? ?? ??? ??? ?result ?= sb2.toString(); // ? ? ? ? ? ??? ?inputStream = conn.getInputStream(); // ? ? ? ? ? ??? ?result = IOUtils.toString(inputStream); ? ? ? ? ? ? }else { ? ? ? ? ? ? ?? ?inputStream = conn.getErrorStream(); ? ? ? ? ? ? ?? ?result = IOUtils.toString(inputStream); ? ? ? ? ? ? ?? ?JSONObject jsonObject = JSONObject.fromObject(result); ? ? ? ? ? ? ?? ?String message = jsonObject.getString("message"); ? ? ? ? ? ? ?? ?result = "{\"errorMsgCodeStatus\":\""+201+"\",\"code\":\""+responseCode+"\",\"message\":\""+message+"\"}"; ? ? ? ? ? ? } ? ? ? ? }catch(Exception e){ ? ? ? ? ?? ?e.printStackTrace(); ? ? ? ? } ? ? ? ? log.info("=====返回状态responseCode:"+responseCode+"返回结果result:"+result); ? ? ? ? return result; ? ? }?
?}
import java.net.HttpURLConnection; import java.net.URLConnection; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; public class SslUtils { ? ? private static void trustAllHttpsCertificates() throws Exception { ? ? ? ? TrustManager[] trustAllCerts = new TrustManager[1]; ? ? ? ? TrustManager tm = new miTM(); ? ? ? ? trustAllCerts[0] = tm; ? ? ? ? SSLContext sc = SSLContext.getInstance("SSL"); ? ? ? ? sc.init(null, trustAllCerts, null); ? ? ? ? HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); ? ? } ? ? static class miTM implements TrustManager,X509TrustManager { ? ? ? ? public X509Certificate[] getAcceptedIssuers() { ? ? ? ? ? ? return null; ? ? ? ? } ? ? ? ? public boolean isServerTrusted(X509Certificate[] certs) { ? ? ? ? ? ? return true; ? ? ? ? } ? ? ? ? public boolean isClientTrusted(X509Certificate[] certs) { ? ? ? ? ? ? return true; ? ? ? ? } ? ? ? ? public void checkServerTrusted(X509Certificate[] certs, String authType) ? ? ? ? ? ? ? ? throws CertificateException { ? ? ? ? ? ? return; ? ? ? ? } ? ? ? ? public void checkClientTrusted(X509Certificate[] certs, String authType) ? ? ? ? ? ? ? ? throws CertificateException { ? ? ? ? ? ? return; ? ? ? ? } ? ? } ? ? /** ? ? ?* 忽略HTTPS请求的SSL证书,必须在openConnection之前调用 ? ? ?* @throws Exception ? ? ?*/ ? ? public static void ignoreSsl() throws Exception{ ? ? ? ? HostnameVerifier hv = new HostnameVerifier() { // 这里就直接返回true,不进行校验 ? ? ? ? ? ? public boolean verify(String urlHostName, SSLSession session) { ? ? ? ? ? ? ? ? System.out.println("Warning: URL Host: " + urlHostName + " vs. " + session.getPeerHost()); ? ? ? ? ? ? ? ? return true; ? ? ? ? ? ? } ? ? ? ? }; ? ? ? ? trustAllHttpsCertificates(); ? ? ? ? HttpsURLConnection.setDefaultHostnameVerifier(hv); ? ? } }
weblogic配置
在weblogic服务的启动配置文件startWeblogic.sh中添加?-DUseSunHttpHandler=true 配置参数。
startWeblogic.sh所在路径可参考:/home/mw/weblogic/wls1036/user_projects/domains/base_domain/bin,具体根据自己的项目来定,配置如下:
项目总结:在项目开发过程总为了保证上线的准确度,尽量搭建一套准生产环境,确保两个环境的基础配置完全一致,这样有问题直接从代码本身查找就可以了,由于基础环境浪费几个小时,身心受煎熬真的不值。?
?引用他人结论:在HTTPS的证书未经权威机构认证的情况下,访问HTTPS站点的两种方法,一种方法是把该证书导入到Java的TrustStore文件中,另一种是自己实现并覆盖JSSE缺省的证书信任管理器类。两种方法各有优缺点,第一种方法不会影响JSSE的安全性,但需要手工导入证书;第二种方法虽然不用手工导入证书,但需要小心使用,否则会带来一些安全隐患。
|