当前位置:   article > 正文

解决HTTPS访问问题(jdk版本过低和证书未安装至应用服务器内)_org.bouncycastle.crypto.tls.tlsclientprotocol

org.bouncycastle.crypto.tls.tlsclientprotocol

本地jdk环境为1.7,访问HTTPS正常,部署到生产环境报Connect Rest错误,多方检查原来正式环境为jdk6,去访问别人的https时报错,下面是通过百度整理的解决方案;

首先要自己重写SSLSocketFactory这个类,

下面是自己重写的这个

  1. package com.mln.frame;
  2. import java.io.ByteArrayInputStream;
  3. import java.io.ByteArrayOutputStream;
  4. import java.io.DataOutputStream;
  5. import java.io.FileInputStream;
  6. import java.io.IOException;
  7. import java.io.InputStream;
  8. import java.io.OutputStream;
  9. import java.net.InetAddress;
  10. import java.net.InetSocketAddress;
  11. import java.net.Socket;
  12. import java.net.UnknownHostException;
  13. import java.security.KeyStore;
  14. import java.security.Principal;
  15. import java.security.SecureRandom;
  16. import java.security.Security;
  17. import java.security.cert.CertificateExpiredException;
  18. import java.security.cert.CertificateFactory;
  19. import java.util.Hashtable;
  20. import java.util.LinkedList;
  21. import java.util.List;
  22. import javax.net.ssl.HandshakeCompletedListener;
  23. import javax.net.ssl.SSLPeerUnverifiedException;
  24. import javax.net.ssl.SSLSession;
  25. import javax.net.ssl.SSLSessionContext;
  26. import javax.net.ssl.SSLSocket;
  27. import javax.net.ssl.SSLSocketFactory;
  28. import javax.security.cert.X509Certificate;
  29. import org.bouncycastle.crypto.tls.Certificate;
  30. import org.bouncycastle.crypto.tls.CertificateRequest;
  31. import org.bouncycastle.crypto.tls.DefaultTlsClient;
  32. import org.bouncycastle.crypto.tls.ExtensionType;
  33. import org.bouncycastle.crypto.tls.TlsAuthentication;
  34. import org.bouncycastle.crypto.tls.TlsClientProtocol;
  35. import org.bouncycastle.crypto.tls.TlsCredentials;
  36. import org.bouncycastle.jce.provider.BouncyCastleProvider;
  37. /**
  38. * 建立一个自己的ssl类
  39. */
  40. public class TLSSocketConnectionFactory extends SSLSocketFactory{
  41. static {
  42. if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
  43. Security.addProvider(new BouncyCastleProvider());
  44. }
  45. }
  46. @Override
  47. public Socket createSocket(Socket socket, final String host, int port,
  48. boolean arg3) throws IOException {
  49. if (socket == null) {
  50. socket = new Socket();
  51. }
  52. if (!socket.isConnected()) {
  53. socket.connect(new InetSocketAddress(host, port));
  54. }
  55. final TlsClientProtocol tlsClientProtocol = new TlsClientProtocol(socket.getInputStream(), socket.getOutputStream(), new SecureRandom());
  56. return _createSSLSocket(host, tlsClientProtocol);
  57. }
  58. @Override public String[] getDefaultCipherSuites() { return null; }
  59. @Override public String[] getSupportedCipherSuites() { return null; }
  60. @Override public Socket createSocket(String host, int port) throws IOException, UnknownHostException { return null; }
  61. @Override public Socket createSocket(InetAddress host, int port) throws IOException { return null; }
  62. @Override public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException { return null; }
  63. @Override public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { return null; }
  64. private SSLSocket _createSSLSocket(final String host, final TlsClientProtocol tlsClientProtocol) {
  65. return new SSLSocket() {
  66. private java.security.cert.Certificate[] peertCerts;
  67. @Override public InputStream getInputStream() throws IOException { return tlsClientProtocol.getInputStream(); }
  68. @Override public OutputStream getOutputStream() throws IOException { return tlsClientProtocol.getOutputStream(); }
  69. @Override public synchronized void close() throws IOException { tlsClientProtocol.close(); }
  70. @Override public void addHandshakeCompletedListener( HandshakeCompletedListener arg0) { }
  71. @Override public boolean getEnableSessionCreation() { return false; }
  72. @Override public String[] getEnabledCipherSuites() { return null; }
  73. @Override public String[] getEnabledProtocols() { return null; }
  74. @Override public boolean getNeedClientAuth() { return false; }
  75. @Override
  76. public SSLSession getSession() {
  77. return new SSLSession() {
  78. /*原本这些方法都是直接throw UnsupportedOperationException 导致看不到真实异常*/
  79. @Override
  80. public int getApplicationBufferSize() {
  81. return 0;
  82. }
  83. @Override public String getCipherSuite() { return null; }
  84. @Override public long getCreationTime() { return 0; }
  85. @Override public byte[] getId() { return null; }
  86. @Override public long getLastAccessedTime() { return 0; }
  87. @Override public java.security.cert.Certificate[] getLocalCertificates() { return null; }
  88. @Override public Principal getLocalPrincipal() { return null; }
  89. @Override public int getPacketBufferSize() { return 0; }
  90. @Override public X509Certificate[] getPeerCertificateChain() throws SSLPeerUnverifiedException { return null; }
  91. @Override public java.security.cert.Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException { return peertCerts; }
  92. @Override public String getPeerHost() { return null; }
  93. @Override public int getPeerPort() { return 0; }
  94. @Override public Principal getPeerPrincipal() throws SSLPeerUnverifiedException { return null; }
  95. @Override public String getProtocol() { return null; }
  96. @Override public SSLSessionContext getSessionContext() { return null; }
  97. @Override public Object getValue(String arg0) { return null; }
  98. @Override public String[] getValueNames() { return null; }
  99. @Override public void invalidate() { return; }
  100. @Override public boolean isValid() { return true; }
  101. @Override public void putValue(String arg0, Object arg1) { return; }
  102. @Override
  103. public void removeValue(String arg0) {
  104. return;
  105. }
  106. };
  107. }
  108. @Override public String[] getSupportedProtocols() { return null; }
  109. @Override public boolean getUseClientMode() { return false; }
  110. @Override public boolean getWantClientAuth() { return false; }
  111. @Override public void removeHandshakeCompletedListener(HandshakeCompletedListener arg0) { }
  112. @Override public void setEnableSessionCreation(boolean arg0) { }
  113. @Override public void setEnabledCipherSuites(String[] arg0) { }
  114. @Override public void setEnabledProtocols(String[] arg0) { }
  115. @Override public void setNeedClientAuth(boolean arg0) { }
  116. @Override public void setUseClientMode(boolean arg0) { }
  117. @Override public void setWantClientAuth(boolean arg0) { }
  118. @Override public String[] getSupportedCipherSuites() { return null; }
  119. @Override
  120. public void startHandshake() throws IOException {
  121. tlsClientProtocol.connect(new DefaultTlsClient() {
  122. @SuppressWarnings("unchecked")
  123. @Override
  124. public Hashtable<Integer, byte[]> getClientExtensions() throws IOException {
  125. Hashtable<Integer, byte[]> clientExtensions = super.getClientExtensions();
  126. if (clientExtensions == null) {
  127. clientExtensions = new Hashtable<Integer, byte[]>();
  128. }
  129. //Add host_name
  130. byte[] host_name = host.getBytes();
  131. final ByteArrayOutputStream baos = new ByteArrayOutputStream();
  132. final DataOutputStream dos = new DataOutputStream(baos);
  133. dos.writeShort(host_name.length + 3);
  134. dos.writeByte(0);
  135. dos.writeShort(host_name.length);
  136. dos.write(host_name);
  137. dos.close();
  138. clientExtensions.put(ExtensionType.server_name, baos.toByteArray());
  139. return clientExtensions;
  140. }
  141. @Override
  142. public TlsAuthentication getAuthentication() throws IOException {
  143. return new TlsAuthentication() {
  144. @Override
  145. public void notifyServerCertificate(Certificate serverCertificate) throws IOException {
  146. try {
  147. KeyStore ks = _loadKeyStore();
  148. CertificateFactory cf = CertificateFactory.getInstance("X.509");
  149. List<java.security.cert.Certificate> certs = new LinkedList<java.security.cert.Certificate>();
  150. boolean trustedCertificate = false;
  151. for ( org.bouncycastle.asn1.x509.Certificate c : serverCertificate.getCertificateList()) {
  152. java.security.cert.Certificate cert = cf.generateCertificate(new ByteArrayInputStream(c.getEncoded()));
  153. certs.add(cert);
  154. String alias = ks.getCertificateAlias(cert);
  155. if(alias != null) {
  156. if (cert instanceof java.security.cert.X509Certificate) {
  157. try {
  158. ( (java.security.cert.X509Certificate) cert).checkValidity();
  159. trustedCertificate = true;
  160. } catch(CertificateExpiredException cee) {
  161. // Accept all the certs!
  162. }
  163. }
  164. } else {
  165. // Accept all the certs!
  166. }
  167. }
  168. if (!trustedCertificate) {
  169. // Accept all the certs!
  170. }
  171. peertCerts = certs.toArray(new java.security.cert.Certificate[0]);
  172. } catch (Exception ex) {
  173. ex.printStackTrace();
  174. throw new IOException(ex);
  175. }
  176. }
  177. @Override
  178. public TlsCredentials getClientCredentials(CertificateRequest certificateRequest) throws IOException {
  179. return null;
  180. }
  181. private KeyStore _loadKeyStore() throws Exception {
  182. FileInputStream trustStoreFis = null;
  183. try {
  184. KeyStore localKeyStore = null;
  185. String trustStoreType = System.getProperty("javax.net.ssl.trustStoreType")!=null?System.getProperty("javax.net.ssl.trustStoreType"):KeyStore.getDefaultType();
  186. String trustStoreProvider = System.getProperty("javax.net.ssl.trustStoreProvider")!=null?System.getProperty("javax.net.ssl.trustStoreProvider"):"";
  187. if (trustStoreType.length() != 0) {
  188. if (trustStoreProvider.length() == 0) {
  189. localKeyStore = KeyStore.getInstance(trustStoreType);
  190. } else {
  191. localKeyStore = KeyStore.getInstance(trustStoreType, trustStoreProvider);
  192. }
  193. char[] keyStorePass = null;
  194. String str5 = System.getProperty("javax.net.ssl.trustStorePassword")!=null?System.getProperty("javax.net.ssl.trustStorePassword"):"";
  195. if (str5.length() != 0) {
  196. keyStorePass = str5.toCharArray();
  197. }
  198. localKeyStore.load(trustStoreFis, keyStorePass);
  199. if (keyStorePass != null) {
  200. for (int i = 0; i < keyStorePass.length; i++) {
  201. keyStorePass[i] = 0;
  202. }
  203. }
  204. }
  205. return localKeyStore;
  206. } finally {
  207. if (trustStoreFis != null) {
  208. trustStoreFis.close();
  209. }
  210. }
  211. }
  212. };
  213. }
  214. });
  215. } // startHandshake
  216. };
  217. }
  218. }

类:TLSSocketConnectionFactory

依赖jar包:

jdk15on-1.60.jar

jdk15on-1.60.jar(2)

然后再写一个httpsConnectionUtils工具类:

  1. package com.mln.frame;
  2. import java.io.BufferedReader;
  3. import java.io.DataOutputStream;
  4. import java.io.InputStreamReader;
  5. import java.net.URL;
  6. import java.net.URLEncoder;
  7. import java.security.cert.CertificateException;
  8. import java.security.cert.X509Certificate;
  9. import java.util.ArrayList;
  10. import java.util.Iterator;
  11. import java.util.List;
  12. import java.util.Map;
  13. import javax.net.ssl.HostnameVerifier;
  14. import javax.net.ssl.HttpsURLConnection;
  15. import javax.net.ssl.SSLContext;
  16. import javax.net.ssl.SSLSession;
  17. import javax.net.ssl.TrustManager;
  18. import javax.net.ssl.X509TrustManager;
  19. import org.apache.commons.lang.StringUtils;
  20. /**
  21. * 本类是解决https访问问题
  22. * @author sun
  23. *
  24. */
  25. public class HttpsConnectUtils {
  26. /**
  27. * 获取url内容
  28. */
  29. public static String getQuery(String desUrl,String method,Map<String,String> params) throws Throwable{
  30. if(!"POST".equalsIgnoreCase(method)){
  31. method="GET";//如果不是POST就认为是GET,至于PUT很少用到,暂时用不到
  32. }
  33. String paramStr="";
  34. if(params!=null && !params.isEmpty()){
  35. List<String> list=new ArrayList<String>();//存放参数
  36. Iterator<String> it=params.keySet().iterator();
  37. while(it.hasNext()){
  38. String key=it.next();
  39. list.add(key+"="+URLEncoder.encode(params.get(key), "utf-8"));
  40. }
  41. paramStr=StringUtils.join(list,"&");
  42. }
  43. //如果是get请求且带有参数
  44. if(!"".equals(paramStr) && "GET".equalsIgnoreCase(method)){
  45. desUrl+="?"+paramStr;
  46. }
  47. URL url = new URL(null,desUrl,new sun.net.www.protocol.https.Handler());
  48. SSLContext sslContext=SSLContext.getInstance("TLS");
  49. TrustManager x509TrustManager=new X509TrustManager() {
  50. @Override
  51. public X509Certificate[] getAcceptedIssuers() {
  52. return null;
  53. }
  54. @Override
  55. public void checkServerTrusted(X509Certificate[] arg0, String arg1)
  56. throws CertificateException {
  57. }
  58. @Override
  59. public void checkClientTrusted(X509Certificate[] arg0, String arg1)
  60. throws CertificateException {
  61. }
  62. };
  63. sslContext.init(null, new TrustManager[]{x509TrustManager}, null);
  64. HttpsURLConnection httpsConn=(HttpsURLConnection) url.openConnection();
  65. httpsConn.setSSLSocketFactory(new TLSSocketConnectionFactory());
  66. httpsConn.setRequestProperty("accept", "*/*");
  67. httpsConn.setRequestProperty("connection", "Keep-Alive");
  68. httpsConn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 7.0; Windows xp)");
  69. httpsConn.setDoOutput(true);
  70. httpsConn.setDoInput(true);
  71. httpsConn.setRequestMethod(method!=null?method:"GET");//默认get
  72. //忽略证书设置
  73. httpsConn.setHostnameVerifier(new HostnameVerifier() {
  74. @Override
  75. public boolean verify(String arg0, SSLSession arg1) {
  76. return true;
  77. }
  78. });
  79. //下面的方法会自动修改请求方式为POST
  80. if(!"".equals(paramStr) && "POST".equalsIgnoreCase(method)){
  81. DataOutputStream out = new DataOutputStream(httpsConn.getOutputStream());
  82. out.writeBytes(paramStr);
  83. out.flush();
  84. out.close();
  85. }
  86. InputStreamReader isr = new InputStreamReader(httpsConn.getInputStream(), "utf-8");
  87. BufferedReader inReader = new BufferedReader(isr);
  88. StringBuffer result = new StringBuffer();
  89. String inputLine;
  90. while ((inputLine = inReader.readLine()) != null) {
  91. result.append(inputLine);
  92. }
  93. // 关闭输入流
  94. inReader.close();
  95. isr.close();
  96. httpsConn.disconnect();//每次请求完毕后关闭链接
  97. return result.toString();
  98. }
  99. }

调用的时候直接按httpsConnectionUtils.getQuery(String desUrl,String method,Map<String,String> params)调用即可。

-----------------------------------------------------------------------

以下为jdk1.8版的工具类,也发下相关的httpsConnectionUtils工具类,如下:

  1. package com.mln.frame;
  2. import java.io.BufferedReader;
  3. import java.io.DataOutputStream;
  4. import java.io.InputStreamReader;
  5. import java.net.URL;
  6. import java.net.URLEncoder;
  7. import java.security.cert.CertificateException;
  8. import java.security.cert.X509Certificate;
  9. import java.util.ArrayList;
  10. import java.util.Iterator;
  11. import java.util.List;
  12. import java.util.Map;
  13. import javax.net.ssl.HostnameVerifier;
  14. import javax.net.ssl.HttpsURLConnection;
  15. import javax.net.ssl.SSLContext;
  16. import javax.net.ssl.SSLSession;
  17. import javax.net.ssl.TrustManager;
  18. import javax.net.ssl.X509TrustManager;
  19. import org.apache.commons.lang.StringUtils;
  20. /**
  21. * 本类是解决https访问问题
  22. * @author sun
  23. *
  24. */
  25. public class HttpsConnectUtils {
  26. /**
  27. * 获取url内容
  28. */
  29. public static String getQuery(String desUrl,String method,Map<String,String> params) throws Throwable{
  30. if(!"POST".equalsIgnoreCase(method)){
  31. method="GET";//如果不是POST就认为是GET,至于PUT很少用到,暂时用不到
  32. }
  33. String paramStr="";
  34. if(params!=null && !params.isEmpty()){
  35. List<String> list=new ArrayList<String>();//存放参数
  36. Iterator<String> it=params.keySet().iterator();
  37. while(it.hasNext()){
  38. String key=it.next();
  39. list.add(key+"="+URLEncoder.encode(params.get(key), "utf-8"));
  40. }
  41. paramStr=StringUtils.join(list,"&");
  42. }
  43. //如果是get请求且带有参数
  44. if(!"".equals(paramStr) && "GET".equalsIgnoreCase(method)){
  45. desUrl+="?"+paramStr;
  46. }
  47. URL url = new URL(null,desUrl,new sun.net.www.protocol.https.Handler());
  48. SSLContext sslContext=SSLContext.getInstance("TLSv1.2");//jdk8支持1.2版本
  49. TrustManager x509TrustManager=new X509TrustManager() {
  50. @Override
  51. public X509Certificate[] getAcceptedIssuers() {
  52. return null;
  53. }
  54. @Override
  55. public void checkServerTrusted(X509Certificate[] arg0, String arg1)
  56. throws CertificateException {
  57. }
  58. @Override
  59. public void checkClientTrusted(X509Certificate[] arg0, String arg1)
  60. throws CertificateException {
  61. }
  62. };
  63. sslContext.init(null, new TrustManager[]{x509TrustManager}, null);
  64. HttpsURLConnection httpsConn=(HttpsURLConnection) url.openConnection();
  65. httpsConn.setSSLSocketFactory(sslContext.getSocketFactory());
  66. httpsConn.setRequestProperty("accept", "*/*");
  67. httpsConn.setRequestProperty("connection", "Keep-Alive");
  68. httpsConn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 7.0; Windows xp)");
  69. httpsConn.setDoOutput(true);
  70. httpsConn.setDoInput(true);
  71. httpsConn.setRequestMethod(method!=null?method:"GET");//默认get
  72. //忽略证书设置
  73. httpsConn.setHostnameVerifier(new HostnameVerifier() {
  74. @Override
  75. public boolean verify(String arg0, SSLSession arg1) {
  76. return true;
  77. }
  78. });
  79. //下面的方法会自动修改请求方式为POST
  80. if(!"".equals(paramStr) && "POST".equalsIgnoreCase(method)){
  81. DataOutputStream out = new DataOutputStream(httpsConn.getOutputStream());
  82. out.writeBytes(paramStr);
  83. out.flush();
  84. out.close();
  85. }
  86. InputStreamReader isr = new InputStreamReader(httpsConn.getInputStream(), "utf-8");
  87. BufferedReader inReader = new BufferedReader(isr);
  88. StringBuffer result = new StringBuffer();
  89. String inputLine;
  90. while ((inputLine = inReader.readLine()) != null) {
  91. result.append(inputLine);
  92. }
  93. // 关闭输入流
  94. inReader.close();
  95. isr.close();
  96. httpsConn.disconnect();//每次请求完毕后关闭链接
  97. return result.toString();
  98. }
  99. }

希望能帮到和我一样苦逼的人!

总相比来说升级jdk肯定是最好方案,不得以才会用上面方法,也感谢其他善于分享经验的人!

--------------------------追加------------

我又采用了另外一种方式,直接升级jdk,但是报错(PKIX:unable to find valid certification path to requested target),后来检查发现,是无法检查到证书导致的,于是通过下载ssl证书,导入到jdk中,重启服务,完美运行。

运行-cmd-cd到%JAVA_HOME%\jre\lib\security\运行以下命令:

keytool -import -file f:\ca.crt -keystore "%JAVA_HOME%\jre\lib\security\cacerts" -alias certServer

注释:

-file f:\ca.crt    证书所在路径

-keystore cacerts ,应该指定全路径 -keystore "%JAVA_HOME%/jre/lib/security/cacerts";

-alias certServer     ,certServer为证书别名,确保唯一

如果发现在执行命令时报错  “keytool不是指定的命令” 错误,请cd到%JAVA_HOME%/jre/bin目录下执行命令。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/145335?site
推荐阅读
相关标签
  

闽ICP备14008679号