使用 SSL 加密的 JDBC 连接 SAP HANA 数据库
近期客户为满足安全要求,提了让业务应用使用 SSL 方式连接 SAP HANA 数据库的需求。本人查询 SAP官方文档 发现数据库支持 SSL 连接,有参数直接加到 JDBC 的 URL 后边就行了,为了便于验证写了个 JDBC 的 demo,在此处记录一二。
准备工作
JdbcTest.java
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;public class JdbcTest {public static Connection getConnection() throws FileNotFoundException, IOException {Connection conn = null;Properties prop = new Properties();try {InputStream in = JdbcTest.class.getResourceAsStream("jdbc.properties");prop.load(in);Class.forName(prop.getProperty("jdbcDriver"));//@formatter:offconn = (Connection) DriverManager.getConnection(prop.getProperty("jdbcUrl"), prop.getProperty("username"),prop.getProperty("password"));//@formatter:on} catch (ClassNotFoundException | SQLException e) {e.printStackTrace();}return conn;}public static void releaseConnection(Connection conn) {try {if (conn != null) {conn.close();System.out.println("Connection has closed");}} catch (SQLException e) {e.printStackTrace();}}public static void main(String[] args) throws FileNotFoundException, IOException {Connection conn = getConnection();if (conn != null)System.out.println("Connection has establish");releaseConnection(conn);}
}
jdbc.properties
jdbcDriver=com.sap.db.jdbc.Driver
jdbcUrl=jdbc:sap://10.2.42.15:30015/?databaseName=Q15&encrypt=true&trustStore=/deployments/SSL/jssecacerts&trustStorePassword=changeit
username=test
password=ABCabc123
InstallCert.java
/** Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.** Redistribution and use in source and binary forms, with or without* modification, are permitted provided that the following conditions* are met:** - Redistributions of source code must retain the above copyright* notice, this list of conditions and the following disclaimer.** - Redistributions in binary form must reproduce the above copyright* notice, this list of conditions and the following disclaimer in the* documentation and/or other materials provided with the distribution.** - Neither the name of Sun Microsystems nor the names of its* contributors may be used to endorse or promote products derived* from this software without specific prior written permission.** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*/
/*** Originally from:* http://blogs.sun.com/andreas/resource/InstallCert.java* Use:* java InstallCert hostname* Example:*% java InstallCert ecc.fedora.redhat.com*/import javax.net.ssl.*;
import java.io.*;
import java.security.KeyStore;
import java.security.MessageDigest;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;/*** Class used to add the server's certificate to the KeyStore* with your trusted certificates.*/
public class InstallCert {public static void main(String[] args) throws Exception {String host;int port;char[] passphrase;if ((args.length == 1) || (args.length == 2)) {String[] c = args[0].split(":");host = c[0];port = (c.length == 1) ? 443 : Integer.parseInt(c[1]);String p = (args.length == 1) ? "changeit" : args[1];passphrase = p.toCharArray();} else {System.out.println("Usage: java InstallCert <host>[:port] [passphrase]");return;}File file = new File("jssecacerts");if (file.isFile() == false) {char SEP = File.separatorChar;File dir = new File(System.getProperty("java.home") + SEP+ "lib" + SEP + "security");file = new File(dir, "jssecacerts");if (file.isFile() == false) {file = new File(dir, "cacerts");}}System.out.println("Loading KeyStore " + file + "...");InputStream in = new FileInputStream(file);KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());ks.load(in, passphrase);in.close();SSLContext context = SSLContext.getInstance("TLS");TrustManagerFactory tmf =TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());tmf.init(ks);X509TrustManager defaultTrustManager = (X509TrustManager) tmf.getTrustManagers()[0];SavingTrustManager tm = new SavingTrustManager(defaultTrustManager);context.init(null, new TrustManager[]{tm}, null);SSLSocketFactory factory = context.getSocketFactory();System.out.println("Opening connection to " + host + ":" + port + "...");SSLSocket socket = (SSLSocket) factory.createSocket(host, port);socket.setSoTimeout(10000);try {System.out.println("Starting SSL handshake...");socket.startHandshake();socket.close();System.out.println();System.out.println("No errors, certificate is already trusted");} catch (SSLException e) {System.out.println();e.printStackTrace(System.out);}X509Certificate[] chain = tm.chain;if (chain == null) {System.out.println("Could not obtain server certificate chain");return;}BufferedReader reader =new BufferedReader(new InputStreamReader(System.in));System.out.println();System.out.println("Server sent " + chain.length + " certificate(s):");System.out.println();MessageDigest sha1 = MessageDigest.getInstance("SHA1");MessageDigest md5 = MessageDigest.getInstance("MD5");for (int i = 0; i < chain.length; i++) {X509Certificate cert = chain[i];System.out.println(" " + (i + 1) + " Subject " + cert.getSubjectDN());System.out.println(" Issuer " + cert.getIssuerDN());sha1.update(cert.getEncoded());System.out.println(" sha1 " + toHexString(sha1.digest()));md5.update(cert.getEncoded());System.out.println(" md5 " + toHexString(md5.digest()));System.out.println();}System.out.println("Enter certificate to add to trusted keystore or 'q' to quit: [1]");String line = reader.readLine().trim();int k;try {k = (line.length() == 0) ? 0 : Integer.parseInt(line) - 1;} catch (NumberFormatException e) {System.out.println("KeyStore not changed");return;}X509Certificate cert = chain[k];String alias = host + "-" + (k + 1);ks.setCertificateEntry(alias, cert);OutputStream out = new FileOutputStream("jssecacerts");ks.store(out, passphrase);out.close();System.out.println();System.out.println(cert);System.out.println();System.out.println("Added certificate to keystore 'jssecacerts' using alias '"+ alias + "'");}private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray();private static String toHexString(byte[] bytes) {StringBuilder sb = new StringBuilder(bytes.length * 3);for (int b : bytes) {b &= 0xff;sb.append(HEXDIGITS[b >> 4]);sb.append(HEXDIGITS[b & 15]);sb.append(' ');}return sb.toString();}private static class SavingTrustManager implements X509TrustManager {private final X509TrustManager tm;private X509Certificate[] chain;SavingTrustManager(X509TrustManager tm) {this.tm = tm;}public X509Certificate[] getAcceptedIssuers() {/** * This change has been done due to the following resolution advised for Java 1.7+http://infposs.blogspot.kr/2013/06/installcert-and-java-7.html**/ return new X509Certificate[0]; //throw new UnsupportedOperationException();}public void checkClientTrusted(X509Certificate[] chain, String authType)throws CertificateException {throw new UnsupportedOperationException();}public void checkServerTrusted(X509Certificate[] chain, String authType)throws CertificateException {this.chain = chain;tm.checkServerTrusted(chain, authType);}}
}
将这三个文件和 ngdbc-2.4.70.jar 上传到服务器目录 /deployments/SSL
,执行编译命令:
cd /deployments/SSL
javac JdbcTest.java
javac InstallCert.java
此时目录中会有三个class文件(有个内部类):
$ ls
InstallCert.class InstallCert$SavingTrustManager.class JdbcTest.class ngdbc-2.4.70.jar
InstallCert.java jdbc.properties JdbcTest.java
导入证书
执行 java InstallCert <域名 或 IP>[:端口号]
,根据提示输入 1
导入证书,公钥证书文件是从数据库端返回的,会被工具类转换成 Java 程序能识别的证书格式(JKS),输出证书到当前目录下的 jssecacerts
,后边要做的就是在 JDBC 连接地址上添加这个证书的绝对位置,使用证书加密连接数据库。
SAP 技术支持人员提供的证书有问题,hostname 与 证书里签得不一样,导致他们给的 cer 证书导入系统后报错如下:
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
引起这个报错的原因不大好定位,使用
InstallCert.java
导入证书时会很清晰地提示证书有问题,而且也不需要额外上传 cer 证书 再执行 keytool 导入证书命令。
验证连接
修改 jdbc.properties
,执行 java -cp ".:ngdbc-2.4.70.jar" JdbcTest
,当出现如下输出而不是报错即连接测试通过。
$ java JdbcTest
Connection has establish
Connection has closed
参考资料:
- https://help.sap.com/viewer/102d9916bf77407ea3942fef93a47da8/1.0.11/en-US/2624cb2191be4f68897b91023ab41d0c.html
- https://www.cnblogs.com/javadeveloper/p/6120041.html
- https://blog.csdn.net/qq_31222053/article/details/94174506
使用 SSL 加密的 JDBC 连接 SAP HANA 数据库相关推荐
- 使用ABAP(ADBC)和Java(JDBC)连接SAP HANA数据库
在表DBCON里维护一条记录,指向HANA数据库.con_ENV里填入HANA数据库的主机名和端口号.如vmXXXX:30015 DATA: ls_new TYPE DBCON.ls_new-con_ ...
- 使用ABAP(ADBC)和Java(JDBC)连接SAP HANA数据库 1
在表DBCON里维护一条记录,指向HANA数据库.con_ENV里填入HANA数据库的主机名和端口号.如vmXXXX:30015 DATA: ls_new TYPE DBCON.ls_new-con_ ...
- 【FineReport】帆软报表平台的安装与连接 SAP HANA 数据库
[FineReport]帆软报表平台的安装与连接 SAP HANA 数据库 1.下载帆软 2.安装软件 3.连接HANA 4.访问数据 1.下载帆软 (1)帆软最新版本软件下载地址:https://w ...
- FineReport 连接 SAP HANA 数据库
FineReport 连接 SAP HANA 数据库 文章目录 FineReport 连接 SAP HANA 数据库 一.拷贝jar包到FR工程 二.设计器中定义数据连接 1.JDBC方式连接 2.X ...
- python获取sap数据_python 连接 SAP HANA 数据库
SAP HANA 是SAP 新的内存数据库: 目前学习python数据处理分析,现在想要连接 SAP HANA 数据库, 发现目前python已经发布了连接 SAP HANA的库 pyhddb 1.需 ...
- Kettle (3) - 连接 SAP Hana 数据库
PDI 7.1 在数据库连接中,没有提供 SAP Hana 数据库的连接选项.需要先在操作系统中安装 SAP Hana Client,然后将驱动程序拷贝到 PDI安装目录/data-integrati ...
- Java 连接SAP Hana数据库
最近项目有用到hana数据库的,记录一下相关资料. hana连接可参考官网:Hana JDBC创建 整个步骤如下: 项目中增加ngdbc.jar,可以从该博客中链接下载com.sap.db.jdbc. ...
- Kettle连接 SAP Hana 数据库
看这篇 https://blog.csdn.net/stone0823/article/details/78629096 如果要下载SAP Hana Client 点这里 https://tools. ...
- Python连接SAP HANA数据库插入数据
工作的时候需要往HANA数据库插入一些测试数据,我使用的连接HANA的工具DBeaver又不能像Mysql那样批量执行多条插入语句,就想用python连接HANA往里循环插入数据,由于代码水平有限,尝 ...
最新文章
- 吴文俊人工智能科学技术奖:陆汝钤院士、百度王海峰等获奖
- fork/join 全面剖析,你可以不用,但是不能不懂!
- 【数据结构与算法-2】链表
- MYSQL视图用户管理
- 四针角oled屏连接arduino_使用Arduino开发板连接OLED显示屏制作一款智能手表
- LeetCode371——Sum of Two Integers(不用+)
- 最新dotCMS SQL注入漏洞 攻击者可获得敏感数据 绿盟科技发布安全威胁通告
- (转)谷歌安卓官方教程中文版
- linux sort排序字符串位数,Linux sort命令详解:字符串排序
- 计算机中心机房设计规范,GB50174-2017 数据中心机房设计规范
- Ubuntu18.04 下的Gif录制工具
- 12月Java原生商城APP源码-完全开源
- 方舟原始恐惧mod生物代码_方舟MOD
- python实现杨辉三角
- 外螺纹对照表_美制螺纹内外径对照表unf
- 现代JS名词概念系列——函数的纯洁性【龟速翻译】
- XML配置文件的读取
- Boardcast03
- DbVisualizer 10破解之后,在输入框使用光标无法准确定位字符
- 基于Android的健康宝体检app介绍(一)