本文介绍配置了SSL链路加密后,如何通过pgAdmin、psql命令行终端以及JDBC连接数据库。

前提条件

使用pgAdmin客户端通过SSL连接RDS PostgreSQL数据库

  1. 启动pgAdmin 4客户端
    说明 高版本客户端首次登录需要设置Master Password用于保护保存的密码和其他凭据。
  2. 右击Servers,选择Create > Server...
  3. General页签设置连接名称。
  4. 选择Connection标签页,输入要连接的实例信息。
    参数 说明
    Hostname/address 主机名称/地址。若通过内网连接,需输入RDS实例的内网连接地址;若使用外网连接,需输入RDS实例的外网连接地址。查看RDS实例的内外网地址及端口请参见查看或修改内外网地址和端口
    Port 连接地址对应的端口。
    Username RDS实例的账号名称。创建RDS实例的账号请参见创建数据库和账号
    Password 账号对应的密码。
  5. 选择SSL标签页,配置SSL认证方式和证书。sslpgadmin
    参数 说明
    SSL mode
    PostgreSQL数据库开启SSL链路加密后,表示允许客户端通过SSL连接数据库,在客户端连接数据库时,请根据以下场景选择SSL mode参数的取值。
    • 数据库未配置客户端访问控制
      • 通过SSL连接时,SSL mode选择Require、Verify-CA或Verify-Full。
      • 不通过SSL连接时,SSL mode选择Disable。
    • 数据库配置了客户端访问控制,客户端必须使用SSL连接,SSL mode选择Require、Verify-CA或Verify-Full。
    Require、Verify-CA和Verify-Full含义如下:
    • Require:只对数据链路加密,并不验证数据库的真实性。
    • Verify-CA:加密数据链路,同时验证数据库的真实性。
    • Verify-Full:加密数据链路,验证数据库的真实性,同时比对证书内的CN或DNS与连接时配置的数据库连接地址是否一致。
    Client certificate 如果完成了配置客户端CA证书,则需要配置此参数,表示客户端证书(client.crt)。
    Client certificate key 如果完成了配置客户端CA证书,则需要配置此参数,表示客户端证书私钥(client.key)。
    Root certificate SSL mode取值为Verify-CAVerify-Full时,需要配置此参数,表示数据库CA证书路径。
    说明 本示例中,数据库CA证书存放路径为C:\CA\,您可以将证书解压到您本地的任意位置。
  6. 单击Save
  7. 若连接信息无误,会出现如下界面,则表示连接成功。
    注意 postgres是RDS实例默认的系统数据库,请勿在该数据库中进行任何操作。

使用psql命令行终端SSL连接RDS PostgreSQL数据库

  1. var/lib/pgsql目录下创建.postgresql文件夹。
    mkdir /var/lib/pgsql/.postgresql
  2. 将如下文件拷贝到.postgresql文件夹中。
    cp client.crt client.key ca1.crt /var/lib/pgsql/.postgresql/
    说明 本示例中,客户端证书(client.crt)、客户端证书私钥(client.key)和数据库CA证书(ca1.crt)存放的路径为当前目录,请根据实际情况配置。
  3. 修改.postgresql文件夹权限。
    chown postgres:postgres /var/lib/pgsql/.postgresql/*
    chmod 600 /var/lib/pgsql/.postgresql/*
  4. 使用如下命令编辑postgres用户的环境变量。
    vim /var/lib/pgsql/.bash_profile
  5. 输入i进入编辑模式,补充如下内容。
    export PGSSLCERT="/var/lib/pgsql/.postgresql/client.crt"
    export PGSSLKEY="/var/lib/pgsql/.postgresql/client.key"
    export PGSSLROOTCERT="/var/lib/pgsql/.postgresql/ca1.crt"
  6. 使用Esc退出编辑模式,然后输入:wq保存并退出。
  7. 重新加载环境变量。
    source .bash_profile
  8. 设置连接时客户端对数据库的认证方式。
    export PGSSLMODE="verify-full"
    PostgreSQL数据库开启SSL链路加密后,表示允许客户端通过SSL连接数据库,在客户端连接数据库时,请根据以下场景选择PGSSLMODE参数的取值。
    数据库是否配置客户端访问控制 是否需要通过SSL连接 PGSSLMODE取值
    require、verify-ca或verify-full
    disable
    必须使用SSL require、verify-ca或verify-full
    说明
    require、verify-ca和verify-full含义如下:
    • require:只对数据链路加密,并不验证数据库的真实性。
    • verify-ca:加密数据链路,同时验证数据库的真实性。
    • verify-full:加密数据链路,验证数据库的真实性,同时比对证书内的CN或DNS与连接时配置的数据库连接地址是否一致。
  9. 连接数据库。
    psql -h <数据库连接地址> -U <用户名> -p <端口号> -d <数据库名>
    各参数在RDS控制台的获取位置:
    参数 获取方式
    数据库连接地址 加密的连接地址,通过SSL页面中保护主机参数获取。
    用户名 通过账号管理页面获取用户名。
    端口号 默认1921,如果您修改过,通过数据库连接页面获取。
    数据库名 postgres是RDS实例默认的系统数据库,请勿在该数据库中进行任何操作。如果您需要连接RDS实例下创建的其他数据库,可从数据库管理页面获取。

使用JDBC SSL连接RDS PostgreSQL数据库

  1. 下载如下文件到本地。
  2. 将客户端私钥(client.key)转换为pk8格式。
    openssl pkcs8 -topk8 -inform PEM -in client.key -outform der -out client.pk8 -v1 PBE-MD5-DES
    # 需要输入密码,连接时需要使用
    Enter Encryption Password:
    Verifying - Enter Encryption Password:
  3. 以Maven项目为例,在pom.xml中导入PostgreSQL的Maven依赖。
     <dependency>
        <groupId>org.postgresql</groupId>
        <artifactId>postgresql</artifactId>
        <version>42.2.10</version>
      </dependency>
  4. 在业务代码中编写JDBC SSL连接PostgreSQL。
     // 设置RDS PostgreSQL实例的连接地址     
     String hostname = "pgm-bpxxxxx.pg.rds.aliyuncs.com";   
     // 设置RDS PostgreSQL实例的连接端口
     String port = "1921";   
     // 设置待连接的数据库名
     String dbname = "postgres";  
    
     String jdbcUrl = "jdbc:postgresql://" + hostname + ":" + port + "/" + dbname+"?binaryTransfer=true";
    
     Properties properties = new Properties();
     // 设置连接数据库的用户名
     properties.setProperty("user", "username"); 
     //设置连接数据库的密码
     properties.setProperty("password", "*****");   
     // 设置证书存放路径 
     String path= "D:\\ssl\\"; 
    
     // 配置以ssl访问
     properties.setProperty("ssl", "true");
     //设置证书授权机构的公钥名
     properties.setProperty("sslrootcert", path + "/" + "root.crt");
     //设置客户端证书私钥名
     properties.setProperty("sslkey", path + "/" + "client.pk8");  
     //设置客户端证书名
     properties.setProperty("sslcert", path + "/" + "client.crt");  
     //填写将私钥key格式转换为pk8格式时设置的密码
     properties.setProperty("sslpassword", "*****"); 
    
     // 配置ssl模式,可选值为require、verify-ca、verify-full
     properties.setProperty("sslmode", "verify-ca"); 
    
      try {
          Class.forName("org.postgresql.Driver");
          Connection connection = DriverManager.getConnection(jdbcUrl, properties);
          //本示例中,假设在postgres数据库中存在表example,此处以查询表example数据为例。
          PreparedStatement preparedStatement = connection.prepareStatement("select * from " +
                  "example");
          ResultSet resultSet = preparedStatement.executeQuery();
          while (resultSet.next()) {
              ResultSetMetaData rsmd = resultSet.getMetaData();
              int columnCount = rsmd.getColumnCount();
              Map map = new HashMap();
              for (int i = 0; i < columnCount; i++) {
                  map.put(rsmd.getColumnName(i + 1).toLowerCase(), resultSet.getObject(i + 1));
              }
              System.out.println(map);
          }
      } catch (Exception exception) {
          exception.printStackTrace();
      }