相关文章推荐
旅行中的打火机  ·  sftp ...·  1 年前    · 
空虚的香烟  ·  FileBeat yml配置文件 ...·  1 年前    · 
礼貌的鸡蛋  ·  为什么win7 ...·  2 年前    · 
解决jdk1.6不支持TLS1.2协议的问题(javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure)
已于 2023-01-04 14:31:13 修改
2021-12-06 17:24:43

问题描述:

发现调用失败(javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure)

原因分析:

B项目使用JDK1.8,https协议支持TLS1.2,而A项目是JDK1.6默认不支持TLS1.2 ,所以导致捂手失败

解决方案:

实际项目通过该方式已解决

引入依赖(jar包下载地址 https://mvnrepository.com/)版本一定跟我保持一致,作者已踩坑

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.54</version>
</dependency>

编写工具类

* 用来请求远程地址,https/http 解决jdk1.6不支持tls1.2的问题 * @author lmc public class TLSSocketConnectionFactory extends SSLSocketFactory { static { if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) { Security.addProvider(new BouncyCastleProvider()); @Override public Socket createSocket(Socket socket, final String host, int port, boolean arg3) throws IOException { if (socket == null) { socket = new Socket(); if (!socket.isConnected()) { socket.connect(new InetSocketAddress(host, port)); final TlsClientProtocol tlsClientProtocol = new TlsClientProtocol(socket.getInputStream(), socket.getOutputStream(), new SecureRandom()); return _createSSLSocket(host, tlsClientProtocol); @Override public String[] getDefaultCipherSuites() { return null; } @Override public String[] getSupportedCipherSuites() { return null; } @Override public Socket createSocket(String host, int port) throws IOException, UnknownHostException { return null; } @Override public Socket createSocket(InetAddress host, int port) throws IOException { return null; } @Override public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException { return null; } @Override public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { return null; } private SSLSocket _createSSLSocket(final String host, final TlsClientProtocol tlsClientProtocol) { return new SSLSocket() { private java.security.cert.Certificate[] peertCerts; @Override public InputStream getInputStream() throws IOException { return tlsClientProtocol.getInputStream(); } @Override public OutputStream getOutputStream() throws IOException { return tlsClientProtocol.getOutputStream(); } @Override public synchronized void close() throws IOException { tlsClientProtocol.close(); } @Override public void addHandshakeCompletedListener( HandshakeCompletedListener arg0) { } @Override public boolean getEnableSessionCreation() { return false; } @Override public String[] getEnabledCipherSuites() { return null; } @Override public String[] getEnabledProtocols() { return null; } @Override public boolean getNeedClientAuth() { return false; } @Override public SSLSession getSession() { return new SSLSession() { /*原本这些方法都是直接throw UnsupportedOperationException 导致看不到真实异常*/ public int getApplicationBufferSize() { return 0; public String getCipherSuite() { return null; } public long getCreationTime() { return 0; } public byte[] getId() { return null; } public long getLastAccessedTime() { return 0; } public java.security.cert.Certificate[] getLocalCertificates() { return null; } public Principal getLocalPrincipal() { return null; } public int getPacketBufferSize() { return 0; } public X509Certificate[] getPeerCertificateChain() throws SSLPeerUnverifiedException { return null; } public java.security.cert.Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException { return peertCerts; } public String getPeerHost() { return null; } public int getPeerPort() { return 0; } public Principal getPeerPrincipal() throws SSLPeerUnverifiedException { return null; } public String getProtocol() { return null; } public SSLSessionContext getSessionContext() { return null; } public Object getValue(String arg0) { return null; } public String[] getValueNames() { return null; } public void invalidate() { return; } public boolean isValid() { return true; } public void putValue(String arg0, Object arg1) { return; } public void removeValue(String arg0) { return; @Override public String[] getSupportedProtocols() { return null; } @Override public boolean getUseClientMode() { return false; } @Override public boolean getWantClientAuth() { return false; } @Override public void removeHandshakeCompletedListener(HandshakeCompletedListener arg0) { } @Override public void setEnableSessionCreation(boolean arg0) { } @Override public void setEnabledCipherSuites(String[] arg0) { } @Override public void setEnabledProtocols(String[] arg0) { } @Override public void setNeedClientAuth(boolean arg0) { } @Override public void setUseClientMode(boolean arg0) { } @Override public void setWantClientAuth(boolean arg0) { } @Override public String[] getSupportedCipherSuites() { return null; } @Override public void startHandshake() throws IOException { tlsClientProtocol.connect(new DefaultTlsClient() { @SuppressWarnings("unchecked") @Override public Hashtable<Integer, byte[]> getClientExtensions() throws IOException { Hashtable<Integer, byte[]> clientExtensions = super.getClientExtensions(); if (clientExtensions == null) { clientExtensions = new Hashtable<Integer, byte[]>(); //Add host_name byte[] host_name = host.getBytes(); final ByteArrayOutputStream baos = new ByteArrayOutputStream(); final DataOutputStream dos = new DataOutputStream(baos); dos.writeShort(host_name.length + 3); dos.writeByte(0); dos.writeShort(host_name.length); dos.write(host_name); dos.close(); clientExtensions.put(ExtensionType.server_name, baos.toByteArray()); return clientExtensions; public TlsAuthentication getAuthentication() throws IOException { return new TlsAuthentication() { public void notifyServerCertificate(Certificate serverCertificate) throws IOException { try { KeyStore ks = _loadKeyStore(); CertificateFactory cf = CertificateFactory.getInstance("X.509"); List<java.security.cert.Certificate> certs = new LinkedList<java.security.cert.Certificate>(); boolean trustedCertificate = false; for ( org.bouncycastle.asn1.x509.Certificate c : serverCertificate.getCertificateList()) { java.security.cert.Certificate cert = cf.generateCertificate(new ByteArrayInputStream(c.getEncoded())); certs.add(cert); String alias = ks.getCertificateAlias(cert); if(alias != null) { if (cert instanceof java.security.cert.X509Certificate) { try { ( (java.security.cert.X509Certificate) cert).checkValidity(); trustedCertificate = true; } catch(CertificateExpiredException cee) { // Accept all the certs! } else { // Accept all the certs! if (!trustedCertificate) { // Accept all the certs! peertCerts = certs.toArray(new java.security.cert.Certificate[0]); } catch (Exception ex) { ex.printStackTrace(); throw new IOException(ex); public TlsCredentials getClientCredentials(CertificateRequest certificateRequest) throws IOException { return null; private KeyStore _loadKeyStore() throws Exception { FileInputStream trustStoreFis = null; try { KeyStore localKeyStore = null; String trustStoreType = System.getProperty("javax.net.ssl.trustStoreType")!=null?System.getProperty("javax.net.ssl.trustStoreType"):KeyStore.getDefaultType(); String trustStoreProvider = System.getProperty("javax.net.ssl.trustStoreProvider")!=null?System.getProperty("javax.net.ssl.trustStoreProvider"):""; if (trustStoreType.length() != 0) { if (trustStoreProvider.length() == 0) { localKeyStore = KeyStore.getInstance(trustStoreType); } else { localKeyStore = KeyStore.getInstance(trustStoreType, trustStoreProvider); char[] keyStorePass = null; String str5 = System.getProperty("javax.net.ssl.trustStorePassword")!=null?System.getProperty("javax.net.ssl.trustStorePassword"):""; if (str5.length() != 0) { keyStorePass = str5.toCharArray(); localKeyStore.load(trustStoreFis, keyStorePass); if (keyStorePass != null) { for (int i = 0; i < keyStorePass.length; i++) { keyStorePass[i] = 0; return localKeyStore; }finally { if (trustStoreFis != null) { trustStoreFis.close(); }); public static JSONObject send(String signData,String signURL,String requestMethod) { // SecurityLogger.logger.info("signURL:"+signURL); // SecurityLogger.logger.info("requestMethod:"+requestMethod); URL myurl = null; try { myurl = new URL(signURL); } catch (Exception e) { e.printStackTrace(); HttpsURLConnection con = null; try { con = (HttpsURLConnection) myurl.openConnection(); con.setSSLSocketFactory(new TLSSocketConnectionFactory()); /*用于解决host name wrong问题,重写主机验证方法,如果请求正常可以去掉*/ con.setHostnameVerifier(new HostnameVerifier(){ public boolean verify(String hostname, SSLSession session) { // TODO Auto-generated method stub return true; }); System.setProperty("sun.net.client.defaultConnectTimeout","300000"); System.setProperty("sun.net.client.defaultReadTimeout", "300000"); if("POST".equals(requestMethod)){ con.setDoOutput(true); con.setDoInput(true); con.setUseCaches(false); con.setInstanceFollowRedirects(true); // con.setRequestProperty("Content-type", "text/xml;charset=utf-8"); // con.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)"); System.out.println("start connect"); con.connect(); System.out.println("end connect"); } catch (Exception e) { e.printStackTrace(); if("POST".equals(requestMethod)){ OutputStream out = null; try { out = con.getOutputStream(); //os = new OutputStreamWriter(out); if(null!=signData){ out.write(signData.getBytes("utf-8")); out.flush(); out.close(); //os.write(signData); //os.flush(); }catch(Exception ex){ ex.printStackTrace(); //接收响应 StringBuffer buffer = null; try { System.out.println("responsecode="+con.getResponseCode()); BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), "utf-8")); buffer=new StringBuffer(); String line=null; while((line=br.readLine())!=null){ buffer.append(line); br.close(); con.disconnect(); } catch (Exception ioex) { ioex.printStackTrace(); System.out.println(buffer!=null?buffer.toString():null); return buffer!=null?JSONObject.parseObject(buffer.toString()):null; // return sb.toString(); public static void main(String[] args) { JSONObject jsonObj = send(null,"https://devau33.cnooc.comss.cn/idp/oauth2/getToken?client_id=tmis&grant_type=authorization_code&client_secret=6c4cf0445ccd42ab8eaf63101e7a4602&code=122","POST"); System.out.println(jsonObj.get("message")); 应用从DMZ迁移到内网后,就不能连接外网了,必须通过代理服务器才能调用第三方接口。使用Nginx作为代理服务器,HTTP的接口代理没有问题,HTPPS的接口代理Java后台总是报错,主要是因为项目使用的JDK1.6,不支持TLS1.2导致握手失败。通过BouncyCastle的第三方jar包可以解决这个问题。也可以使用Nginx的第三方模块ngx_http_proxy_module,配置Nginx作为HTTPS代理服务器解决,不过代码需要修改地方较多。 解压压缩包后文件说明: \doc\conf\nginx.conf:Nginx的转发配置; \doc\conf\haproxy.cfg:Haproxy的转发配置; \doc\conf\proxy\nginx.conf:Nginx作为代理的配置; \doc\gcc:安装Nginx的各个依赖包; \doc\proxy:Nginx的一些源码包,Haproxy源码包,安装步骤可参考readme.txt文件。 最近项目遇到 jdk1.6使用https请求服务器,服务器明确做了协议要求,只支持tls1.2及以上协议。目前的报错是Remote host closed connection during handshake , 通过查阅资料说jdk1.6版本只支持tls1.0 , ssl 3.0 协议,如果用jdk1.6请求tls1.2协议的接口,需要引入第三方库,网上有很多关于调用第三方包重... 火狐浏览器版本:“97.0.1 (64 位)”,打开360网神设备Web管理地址时出现:“此网站可能不支持TLS1.2协议,而这是Firefox支持的最低版本。原本是默认使用https协议打开的,看起来出问题了,网上一堆解决问题,都不行,我就在想把https改为http行不行,试试。当然https的还是继续不行的报错,不过有2个访问方式了而已。内网来的,开发问题不大。先扫描这个设备ip的端口,测试发现220就是ssh端口,密码的话找厂商拿哈,把注释改掉,开启8080监听,默认注释了厂商,如图。 import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.ssl.SSLContexts; 调用: 报错:javax.net.ssl.SSLException: java.lang.RuntimeException: Could not generate DH keypair。由于业务需求,需要将http换成https,在测试中出现了一个问题:也就是JDK1.7可以正常请求而JDK1.6报在请求https请求时,出现致命错误:握手失败。在挣扎了两天后,参考了各路大神的问题方案后,解决了这个问题,一下是我的解决方案。我得项目此时已经解决jdk1.6支持tls1.2协议,jdk1.8默认支持,比较好的解决方案是升级jdk,但是升级jdk风险极大。不能升级jdk的情况下,可以使用如下方式。 <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on<... package nc.impl.pub.filesystem; import org.bouncycastle.crypto.tls.*; import org.bouncycastle.jce.provider.BouncyCastleProvider; import javax.net.ssl.*; import javax... 访问银联的时候,本地环境为jdk1.6,访问https,抛出的异常javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure 解决参考: import java.io.*;importjava.net.UnknownHostException;import java.security.*;import java.security.cert.*;import java.util.*;import javax.net.ssl.*;importjavax.security.cert.X509Certificate;import org.b... It seems that Java 6 supports TLS up to v1.0, is there any way to use TLS 1.2 in Java 6?Maybe a patch or a particular update of Java 6 will have support for it?解决方案Public Oracle Java 6 releases do not...