我们在使用 Spring Web 应用程序进行 Kerberos/AD 身份验证时遇到问题,我认为该问题与 Kerberos 票证的加密类型和 Active Directory 域功能级别有关。
基本设置是:
我有一个环境,其中 Active Directory 域功能级别为 Windows Server 2003,并且一切正常很好,如果客户端登录到域,则可以按预期进行身份验证。使用 kerbtray 检查此环境中的票证,我可以看到它们都具有票证加密类型和密钥加密类型“RSADSI RC4-HMAC”。
我有一个功能级别为 Windows Server 2008 的新域,这是身份验证不起作用的地方。尝试验证票证时返回的应用程序错误是:
Kerberos validation not successful...
Caused by: GSSException: Failure unspecified at GSS-API level (Mechanism level: Checksum failed)
at sun.security.jgss.krb5.Krb5Context.acceptSecContext(Unknown Source)
at sun.security.jgss.GSSContextImpl.acceptSecContext(Unknown Source)
at sun.security.jgss.GSSContextImpl.acceptSecContext(Unknown Source)
at sun.security.jgss.spnego.SpNegoContext.GSS_acceptSecContext(Unknown Source)
at sun.security.jgss.spnego.SpNegoContext.acceptSecContext(Unknown Source)
at sun.security.jgss.GSSContextImpl.acceptSecContext(Unknown Source)
at sun.security.jgss.GSSContextImpl.acceptSecContext(Unknown Source)
at org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator$KerberosValidateAction.run(SunJaasKerberosTicketValidator.java:146)
at org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator$KerberosValidateAction.run(SunJaasKerberosTicketValidator.java:136)
... 34 more
Caused by: KrbException: Checksum failed
at sun.security.krb5.internal.crypto.ArcFourHmacEType.decrypt(Unknown Source)
at sun.security.krb5.internal.crypto.ArcFourHmacEType.decrypt(Unknown Source)
at sun.security.krb5.EncryptedData.decrypt(Unknown Source)
at sun.security.krb5.KrbApReq.authenticate(Unknown Source)
at sun.security.krb5.KrbApReq.<init>(Unknown Source)
at sun.security.jgss.krb5.InitSecContextToken.<init>(Unknown Source)
... 43 more
Caused by: java.security.GeneralSecurityException: Checksum failed
at sun.security.krb5.internal.crypto.dk.ArcFourCrypto.decrypt(Unknown Source)
at sun.security.krb5.internal.crypto.ArcFourHmac.decrypt(Unknown Source)
堆栈跟踪显示“ArcfourCrypto.decrypt”,因此可能将 Kerberos 票证视为 RC4-HMAC。再次使用 kerbtray 检查票证,这次客户端上有 2 个域的票证:krbtgt/.COM。两种票证均具有密钥加密类型 RSADS1 RC4-HMAC,其中一种票证加密类型也具有此类型,但另一种具有“Kerberos AES256-CTS-HMAC-SHA1-96”。
我不确定这是否是问题的原因,但这是我在两个环境中找到的唯一差异,可以解释身份验证异常。我尝试过更改 AD 加密策略,尝试过 IE 和 Firefox,以及几乎所有我能想到的其他方法,但没有任何效果。
任何解决此问题的帮助将不胜感激。我更喜欢在 java 端修复它,因为我可能无法对生产 AD 设置做太多规定。
We are having trouble getting Kerberos/AD authentication to work with a Spring webapp, and I believe the problem has to do with encryption types for the Kerberos tickets and the Active Directory domain functional level.
The basic setup is:
I have one environment where the Active Directory domain functional level is Windows Server 2003 and everything works fine, with clients authenticating as expected if they are logged on to the domain. Using kerbtray to examine the tickets in this environment I can see that they all have both ticket encryption type and key encryption type "RSADSI RC4-HMAC".
I have a new domain with functional level Windows Server 2008, and this is where the authentication does not work. The application error returned when attempting to validate the ticket is:
Kerberos validation not successful...
Caused by: GSSException: Failure unspecified at GSS-API level (Mechanism level: Checksum failed)
at sun.security.jgss.krb5.Krb5Context.acceptSecContext(Unknown Source)
at sun.security.jgss.GSSContextImpl.acceptSecContext(Unknown Source)
at sun.security.jgss.GSSContextImpl.acceptSecContext(Unknown Source)
at sun.security.jgss.spnego.SpNegoContext.GSS_acceptSecContext(Unknown Source)
at sun.security.jgss.spnego.SpNegoContext.acceptSecContext(Unknown Source)
at sun.security.jgss.GSSContextImpl.acceptSecContext(Unknown Source)
at sun.security.jgss.GSSContextImpl.acceptSecContext(Unknown Source)
at org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator$KerberosValidateAction.run(SunJaasKerberosTicketValidator.java:146)
at org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator$KerberosValidateAction.run(SunJaasKerberosTicketValidator.java:136)
... 34 more
Caused by: KrbException: Checksum failed
at sun.security.krb5.internal.crypto.ArcFourHmacEType.decrypt(Unknown Source)
at sun.security.krb5.internal.crypto.ArcFourHmacEType.decrypt(Unknown Source)
at sun.security.krb5.EncryptedData.decrypt(Unknown Source)
at sun.security.krb5.KrbApReq.authenticate(Unknown Source)
at sun.security.krb5.KrbApReq.<init>(Unknown Source)
at sun.security.jgss.krb5.InitSecContextToken.<init>(Unknown Source)
... 43 more
Caused by: java.security.GeneralSecurityException: Checksum failed
at sun.security.krb5.internal.crypto.dk.ArcFourCrypto.decrypt(Unknown Source)
at sun.security.krb5.internal.crypto.ArcFourHmac.decrypt(Unknown Source)
The stack trace shows "ArcfourCrypto.decrypt" so presumably is treating the Kerberos ticket as RC4-HMAC. Using kerbtray again to examine the tickets this time there are 2 tickets on the client for the domain: krbtgt/.COM. Both of tickets have key encryption type RSADS1 RC4-HMAC, one also has this for ticket encryption type, but the other has "Kerberos AES256-CTS-HMAC-SHA1-96".
I don't know for sure that this is the cause of the problem, but it is the only difference I've been able to find in the two environments that might explain the authentication exception. I've tried changing the AD encryption policy, tried IE and Firefox, and pretty much everything else I could think of, but nothing has worked.
Any help addressing this would be much appreciated. I'd prefer to fix it on the java end as I probably can't dictate too much about the production AD setup.
发布评论
评论(2)
问题似乎出在密钥表中。有一些操作序列会导致某些特定的 keytab 文件状态:
(A) keytab 适用于 Java,但不适用于 k5start/kinit;
(B) keytab 不适用于 Java,但适用于 k5start/kinit;
(C) keytab 可以与它们一起使用。
简短的 Java 代码允许检查 Java 是否可以使用 keytab 文件进行身份验证
,以及要使用的属性文件:(
下面我们假设 krb/kdc 已正确安装和配置,数据库是使用 kdb5_util 创建的。起始状态每个命令序列是:删除 keytab 文件、删除令牌缓存、从数据库中删除用户“foo”。)
以下操作序列导致 keytab 状态 (A):
以下操作序列导致 keytab 状态 (B) ):
但是“k5start foo”在这种状态下是可以的,“kinit foo”也是如此。
以下操作序列导致状态 (C):
之后 k5start/kinit 和 java 验证都给出肯定结果。
环境:
在 Java 7 中也观察到相同的行为。
在使用从源发行版编译的 MIT kerberos 5-1.10.3 的 Ubuntu precision (12.04.1 LTS) 上也观察到了相同的行为。
The problem seems to be in the keytab. There are some action sequences leading to some specific keytab file states:
(A) keytab works with Java but does not work with k5start/kinit;
(B) keytab does not work with Java, but works with k5start/kinit;
(C) keytab works with both them.
The short Java code that allows to check if Java can authenticate using the keytab file:
, and the property file to use:
(Below we assume that krb/kdc is correctly installed and configured, the database is created with kdb5_util. The starting state of each command sequence is: the keytab file deleted, token cache is deleted, user "foo" is deleted from the database.)
The following action sequence leads to the keytab state (A):
The following action sequence leads to the keytab state (B):
But the "k5start foo" is okay in this state, as well as "kinit foo".
And the following action sequence leads to state (C):
after that both k5start/kinit and the java verification give positive result.
Environment:
Also the same behavior observed with Java 7.
Also the same behavior was observed on Ubuntu precise (12.04.1 LTS) with MIT's kerberos 5-1.10.3 compiled from the source distribution.
问题在于令牌的生成方式与服务器端的验证方式。从异常跟踪中可以看出,问题在于客户端未设置校验和,而服务器端正在验证校验和。校验和是令牌中设置的参数值之一,具有明显的含义。
2008年一定有办法禁用这个功能来忽略校验和检查。但这打开了另一扇门,您可能需要评估剩余风险。
The problem is with how token is generated vs how it is validated on server side. From the exception trace, it shows the issue is, client side is not setting checksum and server side is looking to validate the checksum. Checksum is one of the params value set in the token which has it obvious meaning.
There must be a way in 2008 to disable this feature to ignore checksum check. But opens another door and you may need to evaluate residual risk.