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

发布日期:2024-07-22 07:05    点击次数:199
背景

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

Oracle启用SSL设置 客户端访问SSL设置(Java客户端, NET客户端) 客户端工具连接访问 Oracle启用SSL设置(以Linux服务器为例) 服务端创建Wallet

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

一般oracle管理,都是会建在单独的oracle用户下
shell复制代码mkdir -p /home/oracle/wallets
cd /home/oracle/wallets #进入当前目录
创建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这个可以自己设置,后面要用到
创建一个自签名的证书
shell复制代码orapki wallet add -wallet ./server_wallet -dn "CN=server" -keysize 1024 -self_signed -validity 365 -pwd Zjzs_123
# 注意路径和密码
发布服务器的wallet信息
shell复制代码orapki wallet display -wallet ./server_wallet
# 注意路径
导出证书信息(秘钥)
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命令提示符

创建客户端wallet
shell复制代码orapki wallet create -wallet E:\client_wallet -auto_login -pwd Zjzs_123

# E:\client_wallet wallet存储路径
# -pwd 证书密码 ,自己设置
创建自签名证书
shell复制代码orapki wallet add -wallet E:\client_wallet -dn "CN=client" -keysize 1024 -self_signed -validity 365 -pwd Zjzs_123

# 注意路径和密码
导出证书信息(秘钥)
shell复制代码orapki wallet export -wallet E:\client_wallet -dn "CN=client" -cert E:\client_wallet\cert.txt

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

图片

图片

服务端和客户端的秘钥互认证 服务端认证客户端秘钥 客户端产生的cert.txt 上传到服务器 (E:\client_wallet\cert.txt) 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的秘钥
客户端认证服务端秘钥 服务端产生的cert.txt 下载到客户端 (/home/oracle/wallets/server_wallet/cert.txt) 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客户端配置证书和连接信息,以及网络服务名,参考前面的客户端连接步骤就行

程序调用

图片

特别说明

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

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

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报。