Java代碼SSL https 加密連接 sqlserver


3種連接sqlserver方式 URL 的區別:

1)jdbc:sqlserver://IP:port;DatabaseName=dbName;autoReconnectForPools=true; 

2)jdbc:sqlserver://IP:port;DatabaseName=dbName;autoReconnectForPools=true;encrypt=true;trustServerCertificate=true;  

3)jdbc:sqlserver://IP:port;DatabaseName=dbName;autoReconnectForPools=true;encrypt=true;trustServerCertificate=false;trustStore=/path/to/truststore.ks;trustStorePassword=12345678;hostNameInCertificate=cer證書里的域名

接下來我們說說這3種連接方式的區別:

一、非加密形式的通用連接方式

jdbc:sqlserver://IP:port;DatabaseName=GatewayV7QA;autoReconnectForPools=true; 

二、無條件信任任何根證書的連接方式

jdbc:sqlserver://IP:port;DatabaseName=GatewayV7QA;autoReconnectForPools=true;encrypt=true;trustServerCertificate=true;  
trustServerCertificate=true;  這個參數 true 表示無條件信任server端返回的任何根證書

三、客戶端需驗證server端SSL證書的連接方式

sqlserver官方文檔地址——如何配置SSL url:

中文:https://docs.microsoft.com/zh-cn/sql/connect/jdbc/connecting-with-ssl-encryption?view=sql-server-ver15

英文:https://docs.microsoft.com/en-us/sql/connect/jdbc/connecting-with-ssl-encryption?view=sql-server-ver15

sqlserver官方文檔地址——如何生成 ks 證書:

中文:https://docs.microsoft.com/zh-cn/sql/connect/jdbc/configuring-the-client-for-ssl-encryption?view=sql-server-ver15

英文:https://docs.microsoft.com/en-us/sql/connect/jdbc/configuring-the-client-for-ssl-encryption?view=sql-server-ver15

 

為了避開我踏過的坑,還是按照我的連接方案往下看吧。首先加上sqlserver的驅動:

<dependency>
    <groupId>com.microsoft.sqlserver</groupId>
    <artifactId>mssql-jdbc</artifactId>
    <version>8.2.1.jre8</version>
    <scope>test</scope>
</dependency>

然后url 連接:

jdbc:sqlserver://IP:port;DatabaseName=dbName;autoReconnectForPools=true;encrypt=true;trustServerCertificate=false;trustStore=/path/to/truststore.ks;trustStorePassword=12345678;hostNameInCertificate=cer證書里的域名 

這里把 trustServerCertificate=false 設置為false,表示不再隨意信任任何server端的根證書了,所以我們需要拿server端的 cer 證書生成客戶端的 ks 證書。

打開cmd窗口,進入 serverXXX.cer 所在路徑,執行Java的 keytool 命令生成我們需要的 truststore.ks 證書 :

keytool -import -v -trustcacerts -aliasA aliasName -file domainA.cer -keystore truststore.ks
keytool -import -v -trustcacerts -aliasB aliasName -file domainB.cer -keystore truststore.ks  //把第二個cer證書壓縮到同一個ks文件里
keytool -import -v -trustcacerts -aliasC aliasName -file domainC.cer -keystore truststore.ks  //把第三個cer證書壓縮到同一個ks文件里

首先驗證是JKS格式證書,其中Keystore type: JKS才行,命令行驗證: keytool -list -rfc -keystore path/truststore.ks

keytool 命令之后會生成 ks 證書,然后配置正確的ks 證書路徑 trustStore=/path/to/truststore.ks 

truststore.ks 證書生成過程中,有兩個步驟需要手工輸入:

Enter keystore password: 12345678             // 這里輸入的密碼就是url連接里的密碼:trustStorePassword=12345678   

Trust this certificate? [no]:  yes

truststore.ks 證書生成過程中,會顯示該 cer 證書包含的信任的server端域名,hostNameInCertificate 這個參數必須配置成這些域名中的一個

SubjectAlternativeName [
  DNSName: domainA.com
  DNSName: domainB.com
  DNSName: domainC.com    // 這里的ABC domain分別對應上面的server ABC.cer證書,所以這個jks證書就能SSL加密訪問三個server了
]

Java代碼驗證SSL連接:

import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;

public class SSL_sqlserver_trustServerCertificate_false_Test {

    static String SSL_URL = "jdbc:sqlserver://IP:port;DatabaseName=dbName;" +
            "autoReconnectForPools=true;ApplicationIntent=ReadOnly;encrypt=true;trustServerCertificate=false;" +
            "trustStore=/path/to/truststore.ks;" +    // 用server端的cer證書生成的ks證書
            "trustStorePassword=12345678;" +  //  truststore.ks 證書生成時的密碼
            "hostNameInCertificate=domain1.com"
            ;
    static String USERNAME = "username";
    static String PASSWORD = "password";

    public static void main(String[] args) throws SQLException, ClassNotFoundException {

        Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
        Connection conn = DriverManager.getConnection(SSL_URL, USERNAME, PASSWORD);
        ResultSet resultSet = conn.createStatement().executeQuery("select 100, 'trustServerCertificate=false'  ");
        while(resultSet.next()){
            int queryInt = resultSet.getInt(1);
            String getString = resultSet.getString(2);
            System.out.println("queryInt==="+queryInt);
            System.out.println("getString::: "+getString);
        }
        conn.close();
    }
}

如果連接成功,控制台打印:

queryInt===100
getString::: trustServerCertificate=false

 

四、報錯解決思路

4.1、InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty  

如果是這個錯誤,表示ks證書路徑不對或者ks證書無效,也就是 trustStore=/path/to/truststore.ks 這個值設置錯了

4.2、no sqljdbc_auth in java.library.path 或者 sqljdbc_auth.dll: unknown file type, first eight bytes: 0x4D 0x5A 0x90 0x00 0x03 0x00 0x00 0x00

這種找 dll 錯誤的貌似都是發生在windows端的錯誤,但是我這里證明了是因為連 trustStore、trustStorePassword、hostNameInCertificate 這3個參數都沒配置所以才會報錯

4.3、SQLServerException: This driver is not configured for integrated authentication

 trustStore、trustStorePassword、hostNameInCertificate 這3個參數都沒配置所以才會報錯

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM