分享

Oracle启用SSL及客户端连接设置

 xfxyxh 2024-04-25 发布于浙江

背景

  基于安全性考虑,除了应用启用SSL访问以外,数据库也要启用SSL访问。涉及几块内容:

  1. Oracle启用SSL设置
  2. 客户端访问SSL设置(Java客户端, NET客户端)
  3. 客户端工具连接访问

Oracle启用SSL设置(以Linux服务器为例)

服务端创建Wallet

主要用于存储产生的一些证书,和秘钥信息

  1. 一般oracle管理,都是会建在单独的oracle用户下
shell
复制代码
mkdir -p /home/oracle/wallets cd /home/oracle/wallets #进入当前目录
  1. 创建auto-login的wallet
shell
复制代码
orapki wallet create -wallet ./server_wallet -auto_login -pwd Zjzs_123 # 其中 ./server_wallet 表示当前路径的server_wallet的文件夹下,也就是/home/oracle/wallets # -pwd Zjzs_123 代表需要秘钥,Zjzs_123这个可以自己设置,后面要用到
  1. 创建一个自签名的证书
shell
复制代码
orapki wallet add -wallet ./server_wallet -dn "CN=server" -keysize 1024 -self_signed -validity 365 -pwd Zjzs_123 # 注意路径和密码
  1. 发布服务器的wallet信息
shell
复制代码
orapki wallet display -wallet ./server_wallet # 注意路径
  1. 导出证书信息(秘钥)
shell
复制代码
orapki wallet export -wallet ./server_wallet -dn "CN=server" -cert ./server_wallet/cert.txt # 注意路径

基本上到这里,服务端的wallet已经搞定 最终生成三个文件 cert.txt (导出证书的秘钥信息,后续用于和客户端进行秘钥认证) cwallet.sso 证书和秘钥 ewallet.p12 证书和秘钥

客户端创建wallet

  客户端一般是Windows环境,注意安装Oracle客户端,以及设置环境变量,如果没有设置环境变量,则进入到$ORACLE_CLIENT_HOME/bin路径下,使用oracle pki命令

启用cmd命令提示符

  1. 创建客户端wallet
shell
复制代码
orapki wallet create -wallet E:\client_wallet -auto_login -pwd Zjzs_123 # E:\client_wallet wallet存储路径 # -pwd 证书密码 ,自己设置
  1. 创建自签名证书
shell
复制代码
orapki wallet add -wallet E:\client_wallet -dn "CN=client" -keysize 1024 -self_signed -validity 365 -pwd Zjzs_123 # 注意路径和密码
  1. 导出证书信息(秘钥)
shell
复制代码
orapki wallet export -wallet E:\client_wallet -dn "CN=client" -cert E:\client_wallet\cert.txt

到此,客户端的wallet和证书已经创建成功 最终生成三个文件 cert.txt (导出证书的秘钥信息,后续用于和服务端进行秘钥认证) cwallet.sso 证书和秘钥 ewallet.p12 证书和秘钥

服务端和客户端的秘钥互认证

服务端认证客户端秘钥

  1. 客户端产生的cert.txt 上传到服务器 (E:\client_wallet\cert.txt)
  2. trust认证
shell
复制代码
orapki wallet add -wallet /home/oracle/wallets/server_wallet -trusted_cert -cert /home/oracle/cert.txt -pwd Zjzs_123 # /home/oracle/wallets/server_wallet服务端wallet路径 # /home/oracle/cert.txt 上传的客户端cert.txt路径 # -pwd Zjzs_123 客户端产生的cert.txt的秘钥

客户端认证服务端秘钥

  1. 服务端产生的cert.txt 下载到客户端 (/home/oracle/wallets/server_wallet/cert.txt)
  2. trust认证
shell
复制代码
orapki wallet add -wallet E:\client_wallet -trusted_cert -cert C:\Users\zace\Documents\cert.txt -pwd Zjzs_123 # E:\client_wallet客户端 wallet路径 # C:\Users\zace\Documents\cert.txt 服务端下载的cert.txt路径 # -pwd Zjzs_123 服务端产生的cert.txt 密码

服务端监听配置

文件路径: $ORACLE_HOME/network/admin/listener.ora

shell
复制代码
SSL_CLIENT_AUTHENTICATION = FALSE WALLET_LOCATION = (SOURCE = (METHOD = FILE) (METHOD_DATA = (DIRECTORY = /home/oracle/wallets/server_wallet) # DIRECTORY = /home/oracle/wallets/server_wallet wallet路径 ) ) SSL_CIPHER_SUITES= (SSL_RSA_WITH_AES_128_CBC_SHA, SSL_DH_anon_WITH_3DES_EDE_CBC_SHA) LISTENER = (DESCRIPTION_LIST = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.xx.xx)(PORT = 1521)) # PROTOCOL = TCP,原始的非SSL连接,继续可以使用,端口默认1521 (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521)) (ADDRESS = (PROTOCOL = TCPS)(HOST = 192.168.xx.xx)(PORT = 2484)) # PROTOCOL = TCPS SSL连接启用TCPS,注意客户端配置的时候也要是TCPS,端口是2484 ) ) # 参考原来的路径,不用参照这个 ADR_BASE_LISTENER = /mnt/oracle

重启监听 lsnrctl stop/start

服务端sqlnet.ora配置

文件路径: $ORACLE_HOME/network/admin/sqlnet.ora

shell
复制代码
NAMES.DIRECTORY_PATH= (TNSNAMES, ONAMES, HOSTNAME) SQLNET.EXPIRE_TIME=2 SQLNET.AUTHENTICATION_SERVICES=(TCPS,NTS) SSL_CLIENT_AUTHENTICATION = FALSE WALLET_LOCATION = (SOURCE = (METHOD = FILE) # (METHOD_DATA = (DIRECTORY = /home/oracle/wallets/server_wallet)) wallet路径 (METHOD_DATA = (DIRECTORY = /home/oracle/wallets/server_wallet)) ) SSL_CIPHER_SUITES= (SSL_RSA_WITH_AES_128_CBC_SHA, SSL_DH_anon_WITH_3DES_EDE_CBC_SHA) # 参考原来的路径,不用参照这个 ADR_BASE = /mnt/oracle

到此为止,服务端的配置基本完成了,客户端可以进行访问了

客户端访问配置

配置客户端的sqlnet.ora

路径 $ORACLE_CLIENT_HOME/network/admin/sqlnet.ora

shell
复制代码
SQLNET.AUTHENTICATION_SERVICES = (NTS) SQLNET.AUTHENTICATION_SERVICES=(TCPS,NTS) SSL_CLIENT_AUTHENTICATION = FALSE WALLET_LOCATION = (SOURCE = (METHOD = FILE) # (DIRECTORY = E:\client_wallet)) 客户端wallet路径 (METHOD_DATA = (DIRECTORY = E:\client_wallet)) ) SSL_CIPHER_SUITES= (SSL_RSA_WITH_AES_128_CBC_SHA, SSL_DH_anon_WITH_3DES_EDE_CBC_SHA)

配置tnsname.ora信息

路径 $ORACLE_CLIENT_HOME/network/admin/tnsname.ora

shell
复制代码
sslName = (DESCRIPTION = # PROTOCOL = TCPS PORT = 2484 这两个是和普通连接有差别的,其他是一样的 (ADDRESS = (PROTOCOL = TCPS)(HOST = 192.168.xx.xxx)(PORT = 2484)) (CONNECT_DATA = (SERVER = DEDICATED)(SERVICE_NAME = sslname)) )

客户端连接测试(navicat,plsql都可以)

注意,连接要使用网络服务名的形式,也就是客户端tnsname.ora配置的网络服务名,直连的方式,因为没有带证书信息是连接不上的

JAVA程序连接启用SSL的Oracle

JDBC直连方式

java
复制代码
public static void getOracleSSLConnection(){ /** * 很重要,比如要执行,注入new OraclePKIProvider(),不然无法解析秘钥文件等 */ Security.insertProviderAt(new OraclePKIProvider(), 3); try { Class.forName("oracle.jdbc.driver.OracleDriver"); } catch (ClassNotFoundException e) { System.out.println("ERROR: Oracle JDBC Driver not found"); e.printStackTrace(); return; } System.out.println("Oracle JDBC Driver Registered!"); Connection connection = null; String hostname = "192.168.xx.xxx"; String port = "2484"; String serviceName = "dbServiceName"; String userName = "username"; String passWord = "password"; /** * 核心连接字符串 * 其中 PROTOCOL=tcps 特别注意,是启动tcps 的 */ String oracleURL = "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=tcps)(HOST="+hostname+")(PORT="+port+")))(CONNECT_DATA=(SERVICE_NAME="+serviceName+")))"; Properties props = new Properties(); props.setProperty("user", userName); props.setProperty("password", passWord); /** * SSL证书信息,这个由服务端配置的时候统一生成,需要后缀是.p12的文件,密码也是在哪个时候生成的 */ props.setProperty("javax.net.ssl.trustStore", "E:\\client_wallet\\ewallet.p12"); props.setProperty("javax.net.ssl.trustStoreType","PKCS12"); //密码,前面创建证书的时候,设置的密码 props.setProperty("javax.net.ssl.trustStorePassword","password"); try { connection = DriverManager.getConnection(oracleURL, props); Statement stmt=connection.createStatement(); //创建语句(Statement) ResultSet res=stmt.executeQuery("select id,name from ssl_table where rownum<=10"); while (res.next()){ System.out.println(res.getString("id")); System.out.println(res.getString("name")); } res.close(); stmt.close(); connection.close(); } catch (SQLException e) { System.out.println("Connection Failed! Check output console"); System.out.println("Error code: " + e.getErrorCode()); System.out.println("SQL State: " + e.getSQLState()); e.printStackTrace(); } }

Druid连接池连接方式

java
复制代码
/** * druid数据源方式访问SSL */ public static void createDruidDataSource(){ /** * 很重要,比如要执行,注入new OraclePKIProvider(),不然无法解析秘钥文件等 */ Security.insertProviderAt(new OraclePKIProvider(), 3); String hostname = "192.168.xx.xx"; String port = "2484"; String serviceName = "dbServiceName"; String userName = "username"; String passWord = "password"; DruidDataSource druidDataSource = new DruidDataSource(); druidDataSource.setDriverClassName("oracle.jdbc.driver.OracleDriver"); /** * 核心连接字符串 * 其中 PROTOCOL=tcps 特别注意,是启动tcps 的 */ druidDataSource.setUrl("jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCPS)(HOST="+hostname+")(PORT="+port+")))(CONNECT_DATA=(SERVICE_NAME="+serviceName+")))"); druidDataSource.setUsername(userName); druidDataSource.setPassword(passWord); druidDataSource.setInitialSize(1); druidDataSource.setMaxActive(1); druidDataSource.setTestOnBorrow(true); Properties props = new Properties(); /** * SSL证书信息,这个由服务端配置的时候统一生成,需要后缀是.p12的文件,密码也是在哪个时候生成的 */ props.setProperty("javax.net.ssl.trustStore", "E://client_wallet/ewallet.p12"); props.setProperty("javax.net.ssl.trustStoreType","PKCS12"); //密码,前面创建证书的时候,设置的密码 props.setProperty("javax.net.ssl.trustStorePassword","password"); druidDataSource.setConnectProperties(props); /** * SSL证书信息,这个由服务端配置的时候统一生成,需要后缀是.p12的文件,密码也是在哪个时候生成的 */ try{ //这里单存是测试方便,正常用mybatis就行 Connection connection =druidDataSource.getConnection(); Statement stmt=connection.createStatement(); //创建语句(Statement) ResultSet res=stmt.executeQuery("select deptno,deptname from dept where rownum<=10"); while (res.next()){ System.out.println(res.getString("deptno")); System.out.println(res.getString("deptname")); } res.close(); stmt.close(); connection.close(); } catch (Exception er){ er.printStackTrace(); } }

和非SSL的差别说明

ini
复制代码
jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=tcps)(HOST="+hostname+")(PORT="+port+")))(CONNECT_DATA=(SERVICE_NAME="+serviceName+")))

其中 PROTOCOL=tcps 要特别注意,这里tcps标识启动ssl,如果不是SSL的时候也可以用这个连接串,就是这里要改成tcp

SSL认证需要额外的jar包

主要是这三个包 oraclekpi.jar osdt_Cert.jar osdt_core.jar

一般oracle服务端,都会有的,根据指定的版本去获取 路径 $ORACLE_HOME/jlib

NET程序连接启用SSL的Oracle

使用Oracle客户端配置证书和连接信息,以及网络服务名,参考前面的客户端连接步骤就行

程序调用

特别说明

  1. 如果使用的是System.Data.OracleClient或者 Oracle.DataAccess.dll这类需要Oracle客户端的驱动 则,连接字符串如下
C#
复制代码
String connectString2 = "Data Source=dbServiceName;User Id=xx;Password=xx";
  1. 如果用的是 Oracle.ManageDataAccess.dll这类免客户端的驱动,用下面的字符串
C#
复制代码
String connectString2 = "Data Source=192.168.xx.xx/dbServiceName;User Id=hr;Password=hr";

和上面的区别就是DataSource要加上IP

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多