通过使用 JDBC 的集成身份验证检测到有缺陷的令牌(机制级别:AP_REP 令牌 ID 不匹配!)

问题描述 投票:0回答:1

尝试通过 JDBC 和与 Kerberos 集成的身份验证从运行在 Linux (RHEL) 上的 Tomcat 应用程序到运行 SQL Server 的 Windows 主机建立数据库连接。不断地碰到:

Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Integrated authentication failed. ClientConnectionId:48e48e7d-9590-4d72-bde7-085fa6df61d8
    at 
    at <Ommitted>
    ... 8 more
Caused by: GSSException: Defective token detected (Mechanism level: AP_REP token id does not match!)
    at sun.security.jgss.krb5.AcceptSecContextToken.<init>(AcceptSecContextToken.java:80)

我的 Windows 和 Evolven Server 都位于同一域 (EVOLVEN.CORP)。我已经配置了两个用户:

  • evolvendbuser(这用于服务原理并运行 SQL 服务)。
  • evolvendbclientuser(此用户用于“客户端”I.E Redhat,并且在 SQL Server 中还有一个集成的身份验证用户作为系统管理员)。

环境看起来像这样,我已经使用以下命令使用volvendbuser用户名和我的MSSQL主机配置了服务原则:

setspn -A MSSQLSvc/mssql-g1cftve.evolven.corp:1433 evolvendbuser

确认我已为我的用户和 MSSQL 主机准备好 SPN。

Registered ServicePrincipalNames for CN=evolvendbuser,CN=Users,DC=evolven,DC=corp:
        MSSQLSvc/mssql-g1cftve.evolven.corp
        MSSQLSvc/mssql-g1cftve.evolven.corp:1433

接下来,我为我的客户端用户 evolvendbclientuser 生成了一个 keytab 文件:

ktpass -princ [email protected] -mapuser EVOLVEN\evolvendbclientuser -crypto ALL -ptype KRB5_NT_PRINCIPAL -pass <password> -out evolvendbclientuser.keytab -SetPass

然后,我获取此密钥文件并将其添加到我的 RHEL 服务器主机,以便与我的 JDBC 和 Jaas 配置一起使用。

Keytab 看起来不错:

[root@evolvenserver opt]# klist -k /etc/evolvendbclientuser.keytab
Keytab name: FILE:/etc/evolvendbclientuser.keytab
KVNO Principal
---- --------------------------------------------------------------------------
   5 [email protected]
   5 [email protected]
   5 [email protected]
   5 [email protected]
   5 [email protected]

我测试过我可以通过以下方式获得门票:

kinit -kt /etc/evolvendbclientuser.keytab [email protected]

还做了:

[root@evolvenserver opt]# kvno MSSQLSvc/mssql-g1cftve.evolven.corp:1433
 MSSQLSvc/mssql-g1cftve.evolven.corp:[email protected]: kvno = 20

我的 JDBC 适配器的 JaaS 配置:

com.sun.security.jgss.krb5.initiate {
    com.sun.security.auth.module.Krb5LoginModule required
    useKeyTab=true
    keyTab="/etc/evolvendbclientuser.keytab"
    storeKey=true
    principal="[email protected]"
    doNotPrompt=true
    debug=true;
};

我的 krb5.conf 文件非常基本:

[libdefaults]
    rnds = false
    default_realm = EVOLVEN.CORP
    dns_lookup_realm = false
    dns_lookup_kdc = false
    ticket_lifetime = 30d
    renew_lifetime = 30d
    forwardable = true
    udp_preference_limit = 0
    default_tgs_enctypes = aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 rc4-hmac
    default_tkt_enctypes = aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 rc4-hmac
    permitted_enctypes = aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 rc4-hmac

[realms]
    EVOLVEN.CORP = {
        kdc = EC2AMAZ-AEHRC46.evolven.corp
        admin_server = EC2AMAZ-AEHRC46.evolven.corp
    }

[domain_realm]
    .evolven.corp = EVOLVEN.CORP
    evolven.corp = EVOLVEN.CORP

当我尝试通过 JDBC 使用集成身份验证连接到 MSSQL 实例时:

java -Djavax.security.auth.useSubjectCredsOnly=false \
     -Djava.security.auth.login.config=/opt/tomcat/bin/jaas.conf \
     -Djava.security.krb5.conf=/etc/krb5.conf \
     -Dsun.security.krb5.debug=true \
     -Dsun.security.spnego.debug=true \
     -jar ms-sqlserver-jdbc-1.0.jar \
     "jdbc:sqlserver://MSSQL-G1CFTVE.evolven.corp:1433;DatabaseName=master;authenticationScheme=JavaKerberos;integratedSecurity=true;trustServerCertificate=true"

我总是得到:

<A bunch of hexdecimal gunk/binary stream>            
Entered Krb5Context.initSecContext with state=STATE_IN_PROCESS
15:00:29.503 [main] INFO Main - Time elapsed: 28941
    Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Integrated authentication failed. ClientConnectionId:a6a73dc6-2b15-46d8-b014-183f8c99c8e2
        at com.microsoft.sqlserver.jdbc.SQLServerConnection.terminate(SQLServerConnection.java:3208)
        at com.microsoft.sqlserver.jdbc.KerbAuthentication.intAuthHandShake(KerbAuthentication.java:178)
        at com.microsoft.sqlserver.jdbc.KerbAuthentication.generateClientContext(KerbAuthentication.java:209)
    Caused by: GSSException: Defective token detected (Mechanism level: AP_REP token id does not match!)
        at sun.security.jgss.krb5.AcceptSecContextToken.<init>(AcceptSecContextToken.java:80)
        at sun.security.jgss.krb5.Krb5Context.initSecContext(Krb5Context.java:755)
        at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImpl.java:248)
        at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImpl.java:179)
        at com.microsoft.sqlserver.jdbc.KerbAuthentication.intAuthHandShake(KerbAuthentication.java:158)
        ... 26 more
  1. 网络对所有流量开放。我可以从 RHEL 主机 ping MSSQL 服务器,所有协议都没有问题。
  2. 我对所有解析为 EVOLVEN.CORP 的服务器进行了 nslookup。
  3. 为了安全起见,我将 SPN 小写,但也尝试使用大写 SPN(即 MSSQLSvc/MSSQL-G1CFTVE.evolven.corp:1433)。还是什么都没有。
  4. AD 内的用户启用 AES-128 和 AES-256 加密。我已经尝试过具有不同加密设置的密钥表。还是什么都没有。
  5. 尝试了 udp_preference_limit = 0 的各种设置。我设置了一个高级别(1800 和 0 来禁用 UDP)。还是没有喜悦。
  6. 我的 MSSQL 服务器接受 TCP 流量,我可以使用 sqlcmd 从 RHEL 服务器连接。

我还能如何调试?完全卡住了。

jdbc active-directory mssql-jdbc
1个回答
0
投票

我希望这可以帮助任何陷入困境的人,但显然我的配置有问题。我从头开始,首先在 Active Directory 中创建两个新用户:

  • evolvendbuser(服务主体用户)
  • evolvendbclientuser(我的 tomcat 服务器上基于客户端的用户)。

设置 evolvedndbuser 来运行我的 SQL Server 服务。然后,在 SQL Server 数据库中为域 [email protected] 用户创建基于 SQL“Windows 身份验证”的登录。

然后我在Windows AD域主机上为我的evolvedndbuser创建了SPN:

setspn -A MSSQLSvc/mssql-g1cftve.evolven.corp:1433 evolvendbuser 
setspn -A MSSQLSvc/mssql-g1cftve.evolven.corp evolvendbuser

确认它们就位:

PS C:\Users\Administrator> setspn -L evolvendbuser
Registered ServicePrincipalNames for CN=evolvendbuser,CN=Users,DC=evolven,DC=corp:
        MSSQLSvc/mssql-g1cftve.evolven.corp:1433
        MSSQLSvc/mssql-g1cftve.evolven.corp

然后我在活动目录服务器上为evolvendbclientuser创建了一个keytab文件。请注意,我将加密参数设置为 ALL,您可以根据需要设置特定的加密算法(AES-128、AES-256)。只需确保您的 kdc 服务器支持该加密类型并且 krb5.conf 文件允许使用该加密类型):

ktpass -princ [email protected] -mapuser EVOLVEN\evolvendbclientuser -crypto ALL -ptype KRB5_NT_PRINCIPAL -pass <password> -out evolvendbclientuser.keytab -SetPass

接下来,我将 keytab 文件上传到 RHEL 服务器的

/etc
目录中。然后更新我的 Jaas 文件以引用新的密钥表文件和主体到我的[电子邮件受保护]

com.sun.security.jgss.krb5.initiate {
    com.sun.security.auth.module.Krb5LoginModule required
    useKeyTab=true
    keyTab="/etc/evolvendbclientuser.keytab"
    storeKey=true
    principal="[email protected]"
    doNotPrompt=true
    debug=true;
};

供参考我的 krb5.conf 文件:

[logging]
    default = FILE:/var/log/krb5libs.log
    kdc = FILE:/var/log/krb5kdc.log
    admin_server = FILE:/var/log/kadmind.log

[libdefaults]
    rnds = false
    default_realm = EVOLVEN.CORP
    dns_lookup_realm = false
    dns_lookup_kdc = false
    ticket_lifetime = 30d
    renew_lifetime = 30d
    forwardable = true
    udp_preference_limit = 0
    default_tgs_enctypes = aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 rc4-hmac
    default_tkt_enctypes = aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 rc4-hmac
    permitted_enctypes = aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 rc4-hmac

[realms]
    EVOLVEN.CORP = {
        kdc = EC2AMAZ-AEHRC46.evolven.corp
        admin_server = EC2AMAZ-AEHRC46.evolven.corp
    }

最后,我厌倦了启动 Tomcat 应用程序并等待它失败,因此我编写了一个小 Java 应用程序,您可以将其与 JDBC 适配器一起编译以测试连接:

您需要将其放入与 mssql-jdbc jar 相同的目录中。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class JDBCConnectionWrapper {

    public static void main(String[] args) {
        // Check if a connection string is provided as an argument
        if (args.length < 1) {
            System.out.println("Please provide the JDBC connection string as an argument.");
            System.exit(1);
        }

        // Capture the JDBC connection string from the command-line argument
        String jdbcUrl = args[0];

        System.out.println("Connecting to: " + jdbcUrl);

        try (Connection connection = DriverManager.getConnection(jdbcUrl)) {
            System.out.println("Connected to the database!");
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

然后您可以编译并测试 JDBC 连接性。请注意告诉 JDBC 适配器使用 krb5.conf 文件的附加参数以及供 JDBC 适配器使用的 JaaS 配置。还增加了日志记录。

java -Djavax.security.auth.useSubjectCredsOnly=false \
     -Djava.security.auth.login.config=/opt/tomcat/bin/jaas.conf \
     -Djava.security.krb5.conf=/etc/krb5.conf \
     -Dsun.security.krb5.debug=true \
     -Dsun.security.spnego.debug=true \
     -cp .:mssql-jdbc-7.2.2.jre8.jar JDBCConnectionWrapper \
     "jdbc:sqlserver://MSSQL-G1CFTVE.evolven.corp:1433;DatabaseName=master;authenticationScheme=JavaKerberos;integratedSecurity=true;trustServerCertificate=true"

现在不再出现可怕的“集成身份验证失败”和检测到有缺陷的令牌(机制级别:AP_REP 令牌 ID 不匹配!)错误。我得到:

Entered Krb5Context.initSecContext with state=STATE_IN_PROCESS
>>> EType: sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType
Krb5Context setting peerSeqNumber to: 813842378
Connected to the database!

非常感谢大家!如果您正在为此苦苦挣扎,我希望这会有所帮助!

© www.soinside.com 2019 - 2024. All rights reserved.