java - Oracle 11g,使用 TLSv1.2 与 Java 存储过程的 HTTPS 连接
问题描述
我有两台运行 Oracle 11g 的独立服务器。
这些服务器使用 Oracle 补丁集进行了修补以升级 JVM。升级后,我可以使用 HTTPS 和 TLSv1.2 与外部 Web 服务通信,但只能在服务器“A”上。服务器“B”给了我这样的错误:
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java)
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:142)
at FursTestBaza.Test(FursTestBaza:92)
我们检查了补丁集,并且两台服务器都“安装了”相同的补丁集:
Java 存储过程是一个简单Class
的静态方法。此过程从文件系统加载证书并与指定 URL 建立 HTTPS 连接(硬编码用于测试目的)。在源代码中,我包含System.setProperty("javax.net.debug", "all")
了一些日志以获取正在发生的事情。
Java存储过程源码:
CREATE OR REPLACE AND RESOLVE JAVA SOURCE NAMED INIS_PROD."FursTestBaza" as
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.util.Enumeration;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
public class FursTestBaza {
static String napaka="";
public static void Test()
{
try
{
String URL = "https://blagajne.fu.gov.si:9003/v1/cash_registers";
System.out.println("Testiranje povezave na: " + URL);
System.setProperty("javax.net.debug", "all");
System.out.println("==================================");
System.out.println("1");
KeyStore p12 = KeyStore.getInstance("pkcs12");
String geslo = "*******"; //private key password
System.out.println("2");
p12.load(new FileInputStream(new File("/oracle/orasw/Wallet/Certifikat/Furs/privateCert/FURS-AS_davcne_blagajne.p12")), geslo.toCharArray());
Enumeration e = p12.aliases();
String alias = (String) e.nextElement();
System.out.println("alias certifikata: " + alias);
//privatni ključ
Key privateKey = p12.getKey(alias, geslo.toCharArray());
System.out.println("3");
//podpis
Signature podpis = Signature.getInstance("SHA256WithRSA");
podpis.initSign((PrivateKey) privateKey);
System.out.println("4");
//določimo svoj keystore in TLS1.2
SSLContext sslcontext = SSLContext.getInstance("TLSv1.2");
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
KeyStore ks = KeyStore.getInstance("PKCS12");
System.out.println("5");
ks.load(new FileInputStream(new File("/oracle/orasw/Wallet/Certifikat/Furs/privateCert/FURS-AS_davcne_blagajne.p12")), geslo.toCharArray());
kmf.init(ks, geslo.toCharArray());
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Certificate ca = cf.generateCertificate(new FileInputStream(new File("/oracle/orasw/Wallet/Certifikat/Furs/privateCert/blagajne.fu.gov.si.cer")));
System.out.println("6");
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
System.out.println("7");
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keyStore);
System.out.println("8");
TrustManager[] tm = tmf.getTrustManagers();
sslcontext.init(kmf.getKeyManagers(), tm, null);
System.out.println("8.1");
HttpsURLConnection.setDefaultSSLSocketFactory(sslcontext.getSocketFactory());
System.out.println("9");
URL url = new URL(URL);
HttpsURLConnection httpsURLConnection = (HttpsURLConnection) url.openConnection();
System.out.println("10");
httpsURLConnection.connect();
System.out.println("Povezan na: " + URL + ", chiper:" + httpsURLConnection.getCipherSuite());
System.out.println("Prekinjam povezavo...");
httpsURLConnection.disconnect();
System.out.println("Povezava zaprta.");
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
然后用 PL/SQL 执行了这段代码:
begin
dbms_java.set_output(500000);
p_test_furs;
end;
来自服务器 A 的连接工作正常,一切正常,但问题出在服务器 B 上。
在服务器“B”上我得到了异常(上图),如果比较javax.net.debug
我注意到这个异常:
两台服务器上的证书相同。
我的数据库上的 Java 版本是相同的:
服务器 A:
select dbms_java.get_ojvm_property(propstring=>'java.version') from dual
返回:1.6.0_191
服务器 B:
select dbms_java.get_ojvm_property(propstring=>'java.version') from dual
返回:1.6.0_191
有什么问题或者我可以在服务器/数据库端检查什么?
解决方案
推荐阅读
- firebase - 如何删除 Source.CACHE 中的特定 Firestore 文档?
- node.js - 如何设置 Twilio 工人统计数据的开始和结束日期?
- android - 如何使子 ImageView 采取父 MaterialCardView 的形状外观?
- collision-detection - 如何在 Phaser 3 中使用物质物理从我的瓦片平台创建平台?
- python - Pyautogui 未导入“没有名为 'pyautogui' 的模块”
- python - 应该是无限循环
- c++ - 在 VSCode 中使用 MSVS 编译器构建 OpenCV 应用程序
- python-3.x - 解压字典字典参数,并在多处理池中使用 **kwargs
- javascript - 当第二个可观察值发生变化时,combineLatest 没有发出?
- spring - 将数据从控制器传递到 ChartJS