[英]"GSSException Defective token detected" - when trying to Authenticate to Tomcat running on Windows using Kerberos
I am struggling to authenticate to a Java web container (I've tried both Tomcat and Jetty) when running on Windows 2012.在 Windows 2012 上运行时,我正在努力验证 Java web 容器(我已经尝试过 Tomcat 和 Jetty)。
Every time I try the Negotiate auth scheme I get an error: org.ietf.jgss.GSSException: Defective token detected (Mechanism level: GSSHeader did not find the right tag)
每次尝试协商身份验证方案时,我都会收到错误消息: org.ietf.jgss.GSSException: Defective token detected (Mechanism level: GSSHeader did not find the right tag)
Steps to reproduce重现步骤
Start out by setting up a Windows Server 2012 or 2016 instance and install active directory domain services.首先设置一个 Windows Server 2012 或 2016 实例并安装活动目录域服务。
In my example, I created:在我的示例中,我创建了:
NETBIOS Domain: NICKIS NETBIOS 域: NICKIS
Dns domain: nickis.life Dns 域名: nickis.life
Create the kerberos subject user on Active Directory在 Active Directory 上创建 kerberos 主题用户
IMPORTANT: MAKE SURE THAT THE FIRST NAME, LAST NAME AND FULL NAME ARE THE SAME!重要提示:确保名字、姓氏和全名相同!
The new user in my case is:我的新用户是:
DN = CN=kerberos500,CN=Users,DC=nickis,DC=life
DN = CN=kerberos500,CN=Users,DC=nickis,DC=life
login+domain = kerberos500@nickis.life
登录+域= kerberos500@nickis.life
NETBIOS\samAccountName = NICKIS\kerberos500
NETBIOS\samAccountName = NICKIS\kerberos500
Run the setspn command from the Windows Active Directory Server从 Windows Active Directory 服务器运行 setspn 命令
setspn -A HTTP/nickis.life@NICKIS.LIFE kerberos500
Example output:示例 output:
C:\Users\Administrator>setspn -A HTTP/nickis.life kerberos500
Checking domain DC=nickis,DC=life
Registering ServicePrincipalNames for CN=kerberos500,CN=Users,DC=nickis,DC=life
HTTP/kerberos500.nickis.life
Updated object
Run the ktpass command from the Windows Active Directory Server从 Windows Active Directory 服务器运行 ktpass 命令
ktpass -out c:\Users\Administrator\kerberos500.keytab -princ HTTP/nickis.life@NICKIS.LIFE -mapUser kerberos500 -mapOp set -pass XXXXpasswordforkerberos500userXXXX -crypto DES-CBC-MD5 -pType KRB5_NT_PRINCIPAL +DesOnly
Example output:示例 output:
C:\Users\Administrator>ktpass -out c:\Users\Administrator\kerberos500.keytab -princ HTTP/nickis.life@NICKIS.LIFE -mapUser kerberos500 -mapOp set -pass xxxxxxxx -crypto DES-CBC-MD5 -pType KRB5_NT_PRINCIPAL +DesOnly
Targeting domain controller: WIN-OVV6VHBGIB8.nickis.life
Using legacy password setting method
Successfully mapped HTTP/kerberos500.nickis.life to kerberos500.
Key created.
Output keytab to c:\Users\Administrator\kerberos500.keytab:
Keytab version: 0x502
keysize 71 HTTP/kerberos500.nickis.life@NICKIS.LIFE ptype 1 (KRB5_NT_PRINCIPAL) vno 3 etype 0x3 (DES-CBC-MD5) keylength 8 (0xcd07200bea625d20)
Account kerberos500 has been set for DES-only encryption.
At this point, you will now have a keytab file:此时,您现在将拥有一个密钥表文件:
c:\Users\Administrator\kerberos500.keytab
And a user principal:和一个用户主体:
HTTP/kerberos500.nickis.life@NICKIS.LIFE
These are the 2 inputs that are needed to provide to the GSSApi to get single sign on with Kerberos.这些是需要提供给 GSSApi 以使用 Kerberos 进行单点登录的 2 个输入。
So I deployed those inputs to my web container's kerberos security realm in the Hadoop security module.因此,我将这些输入部署到我的 web 容器的 Hadoop 安全模块中的 kerberos 安全 realm。
Curl test I tried unsuccessfully to use curl to test it: Curl 测试我尝试使用curl 测试未成功:
curl --negotiate -u: http://nickis.life:8080/my/webapp
Inte.net Explorer test I also tried using Inte.net Explorer. Inte.net Explorer 测试我也试过使用 Inte.net Explorer。 I added nickis.life
domain to the Trusted Roles in Inte.net Explorer.我将nickis.life
域添加到 Inte.net Explorer 中的受信任角色。 Then I launch the site in inte.net explorer: http://nickis.life:8080然后我在 inte.net 资源管理器中启动站点: http://nickis.life:8080
Either way, I get the error below:无论哪种方式,我都会收到以下错误:
org.apache.hadoop.security.authentication.client.AuthenticationException: GSSException: Defective token detected (Mechanism level: GSSHeader did not find the right tag)
at org.apache.hadoop.security.authentication.server.KerberosAuthenticationHandler.authenticate(KerberosAuthenticationHandler.java:398) ~[hadoop-auth-2.7.1.jar:?]
...
Caused by: org.ietf.jgss.GSSException: Defective token detected (Mechanism level: GSSHeader did not find the right tag)
at sun.security.jgss.GSSHeader.<init>(Unknown Source) ~[?:1.8.0_131]
at sun.security.jgss.GSSContextImpl.acceptSecContext(Unknown Source) ~[?:1.8.0_131]
at sun.security.jgss.GSSContextImpl.acceptSecContext(Unknown Source) ~[?:1.8.0_131]
at org.apache.hadoop.security.authentication.server.KerberosAuthenticationHandler$2.run(KerberosAuthenticationHandler.java:365) ~[hadoop-auth-2.7.1.jar:?]
at org.apache.hadoop.security.authentication.server.KerberosAuthenticationHandler$2.run(KerberosAuthenticationHandler.java:347) ~[hadoop-auth-2.7.1.jar:?]
at java.security.AccessController.doPrivileged(Native Method) ~[?:1.8.0_131]
at javax.security.auth.Subject.doAs(Unknown Source) ~[?:1.8.0_131]
at org.apache.hadoop.security.authentication.server.KerberosAuthenticationHandler.authenticate(KerberosAuthenticationHandler.java:347) ~[hadoop-auth-2.7.1.jar:?]
I am stumped.我很难过。 NOTE: I have found several links around here and there but none of them were all inclusive on the steps that were followed like I have summed up here, and none of the solutions provided within worked for me.注意:我在这里和那里找到了几个链接,但没有一个链接像我在这里总结的那样包含所有遵循的步骤,并且其中提供的解决方案都不适合我。
A
record.我尝试在域服务器中将 DNS 设置为A
记录。Can anyone trace what I am screwing up here?谁能追踪我在这里搞砸了什么?
UPDATE:更新:
fusionis.life
, and the AD server is WIN-OVV6VHBGIB8.fusionis.life
我有域设置为fusionis.life
的 AD 服务器,AD 服务器是WIN-OVV6VHBGIB8.fusionis.life
DESKTOP-VTPBE99.fusionis.life
dnsmgmt.msc
and added a "Forward Lookup Zone" with "kerberos500.nickis.life" with A HOST set to the IP of the DESKTOP-VTPBE99.fusionis.life
box.我打开dnsmgmt.msc
并添加了一个带有“kerberos500.nickis.life”的“正向查找区域”,其中主机设置为DESKTOP-VTPBE99.fusionis.life
框的 IP。 C:\Users\Administrator>ktpass -out c:\Users\Administrator\kerberos500.keytab -princ HTTP/kerberos500.nickis.life@NICKIS.LIFE -mapUser kerberos500 -mapOp set -pass xxxxxxxxx -crypto ALL -pType KRB5_NT_PRINCIPAL Targeting domain controller: WIN-OVV6VHBGIB8.fusionis.life Using legacy password setting method Successfully mapped HTTP/kerberos500.nickis.life to kerberos500. Key created. Key created. Key created. Key created. Key created. Output keytab to c:\Users\Administrator\kerberos500.keytab: Keytab version: 0x502 keysize 67 HTTP/kerberos500.nickis.life@NICKIS.LIFE ptype 1 (KRB5_NT_PRINCIPAL) vno 4 etype 0x1 (DES-CBC-CRC) keylength 8 (0x04e30b9183ba8389) keysize 67 HTTP/kerberos500.nickis.life@NICKIS.LIFE ptype 1 (KRB5_NT_PRINCIPAL) vno 4 etype 0x3 (DES-CBC-MD5) keylength 8 (0x04e30b9183ba8389) keysize 75 HTTP/kerberos500.nickis.life@NICKIS.LIFE ptype 1 (KRB5_NT_PRINCIPAL) vno 4 etype 0x17 (RC4-HMAC) keylength 16 (0xe39a141de38abd8750bf9c0bf49fd1c5) keysize 91 HTTP/kerberos500.nickis.life@NICKIS.LIFE ptype 1 (KRB5_NT_PRINCIPAL) vno 4 etype 0x12 (AES256-SHA1) keylength 32 (0xe368a1b060cfe4816f522c1c5f62ca07fe201ed96c6d018054dfbd5b86251892) keysize 75 HTTP/kerberos500.nickis.life@NICKIS.LIFE ptype 1 (KRB5_NT_PRINCIPAL) vno 4 etype 0x11 (AES128-SHA1) keylength 16 (0x1b1a548fa2893a78c6f4c7f9c482b614)
I saved the keytab updated file on the server, then updated the Service Principal to HTTP/kerberos500.nickis.life@NICKIS.LIFE
我将 keytab 更新文件保存在服务器上,然后将服务主体更新为HTTP/kerberos500.nickis.life@NICKIS.LIFE
I logged into tomcat machine as a domain user, added http://kerberos500.nickis.life to the trusted sites, then navigated to http://kerberos500.nickis.life:8764我以域用户身份登录 tomcat 机器,将http://kerberos500.nickis.life添加到受信任的站点,然后导航到http://kerberos500.nickis.life:8764
I checked all combinations of the encryption check boxes in the kerberos500 AD "account" tab.我检查了 kerberos500 AD“帐户”选项卡中加密复选框的所有组合。
Now i'm getting a new error...现在我收到一个新错误...
GSSException: No valid credentials provided (Mechanism level: Failed to find any Kerberos credentails)
UPDATE:更新:
Resolved finally.终于解决了。 I got this final error because I needed fusionis.life
to be on the same host as nickis.life
我收到最后一个错误是因为我需要fusionis.life
与nickis.life
位于同一主机上
The error “ Defective token detected ” likely means that an ntlm token was detected. 错误“ 检测到有缺陷的令牌 ”可能意味着检测到ntlm令牌。 That's what the Negotiate mechanism uses inside popular web browsers if kerberos fails - when not instructed by the web server otherwise. 如果kerberos失败,这就是Negotiate机制在流行的Web浏览器中使用的内容 - 否则Web服务器没有指示。 On windows operating systems, the IE web browser on it (and Firefox, if configured correctly) basically says, if you won't do Kerberos, I'm going to send you an NTLM token. 在Windows操作系统上,IE上的IE浏览器(以及Firefox,如果配置正确)基本上说,如果你不做Kerberos,我会发给你一个NTLM令牌。 And the server replies “no way” I don't even know NTLM so I'm calling what you sent me defective. 服务器回复“没办法”我甚至不知道NTLM所以我打电话给你发送给我的有缺陷。 Since you seem to be setting this up for the first time, you likely did not configure any fallback mechanism (such as NTLM) for when Kerberos fails, therefore, that error message. 由于您似乎是第一次进行此设置,因此您可能没有为Kerberos失败时配置任何回退机制(例如NTLM),因此,该错误消息。 We solve this by understanding why Kerberos is failing. 我们通过理解Kerberos失败的原因来解决这个问题。 I think I see the reason for the failure in your question, in two places, related to SPNs and Trusted Sites. 我想我在两个地方看到了与SPN和可信站点相关的问题失败的原因。 Even if you resolve those two items, there is a third reason and fourth reason why it could continue to fail, related to encryption. 即使你解决了这两个问题,还有第三个原因和第四个原因,它可能会继续失败,与加密有关。
How to properly re-generate the keytab: You should not run the setspn -a command to add an SPN to an AD user whenever you are planning to make a keytab associated with that user account. 如何正确地重新生成密钥表:只要计划创建与该用户帐户关联的密钥表,就不应运行setspn -a命令将ADN添加到AD用户。 The reason why is because the keytab creation command adds the SPN to the user account as part of the command. 原因是因为keytab creation命令将SPN作为命令的一部分添加到用户帐户。 If your scenario doesn't work after following my advice above, then you'll need to remove the SPN via setspn -D like below: 如果按照上面的建议后你的方案不起作用,那么你需要通过setspn -D删除SPN,如下所示:
setspn -D HTTP/nickis.life@NICKIS.LIFE kerberos500
And the re-generate the keytab afterwards, my only change is that I told it to use all encryption types. 然后重新生成密钥表,我唯一的变化是我告诉它使用所有加密类型。 The client and server will agree on the strongest common one during the authentication process. 客户端和服务器将在身份验证过程中就最强大的常见协议达成一致。
ktpass -out c:\Users\Administrator\kerberos500.keytab -princ HTTP/nickis.life@NICKIS.LIFE -mapUser kerberos500 -mapOp set -pass XXXXpasswordforkerberos500userXXXX -crypto ALL -pType KRB5_NT_PRINCIPAL
Then replace the old keytab with the new one. 然后用新的keytab替换旧的keytab。 For additional in-depth information on keytabs, you can read more from my technical article on how to create Kerberos keytabs here: Kerberos Keytabs – Explained . 有关keytabs的更多深入信息,您可以在我的技术文章中阅读更多有关如何在此处创建Kerberos keytabs的信息: Kerberos Keytabs - 解释 。 I frequently go back and edit it based on questions I see here in this forum. 我经常回过头来根据我在这个论坛中看到的问题进行编辑。
By the way, HTTP/kerberos500.nickis.life is a service principal, not a user principal as you wrote in your question. 顺便说一句, HTTP / kerberos500.nickis.life是一个服务主体,而不是你在问题中写的用户主体。 I only use web browsers to test Kerberos in HTTP scenarios like this one, I don't use cURL. 我只使用Web浏览器在像这样的HTTP场景中测试Kerberos,我不使用cURL。
I am positive if you diligently go through all four points I've highlighted above, you will resolve this problem. 如果你努力地完成我上面提到的所有四点,我会很肯定你会解决这个问题。
EDIT1: This answer assumes you have an HTTP service running on a host with the fully-qualified domain name of kerberos500.nickis.life. EDIT1:此答案假设您在具有完全限定域名kerberos500.nickis.life的主机上运行HTTP服务。 If you don't have such a host with that name, my answer will slightly change. 如果你没有这样名字的主持人,我的回答会略有变化。 Please let me know if any. 如果有的话请告诉我。
EDIT2: To achieve the objective of authentication using the URL of http://nickis.life:8080 , then you may keep on using the same keytab you already created. 编辑2:要使用http://nickis.life:8080的URL实现身份验证的目标,您可以继续使用您已创建的相同密钥表。
On the AD account NICKIS\\kerberos500, go to the Account tab, scroll to the bottom, and check the box for "Use Kerberos DES encryption types for this account". 在AD帐户NICKIS \\ kerberos500上,转到“帐户”选项卡,滚动到底部,然后选中“为此帐户使用Kerberos DES加密类型”复选框。
Then enable DES encryption itself at the AD domain level via Group Policy. 然后通过组策略在AD域级别启用DES加密。 To do that, conduct the following: 为此,请执行以下操作:
Reference: Windows Configurations for Kerberos Supported Encryption Type 参考: Kerberos支持的加密类型的Windows配置
EDIT 3: Avoid running Kerberos KDC (the DC), client and server on the same machine. 编辑3:避免在同一台机器上运行Kerberos KDC(DC),客户端和服务器。 That is a classic recipe for getting the "Defective token error" even if you've done everything else right. 这是获得“瑕疵令牌错误”的经典方法,即使你已经做了其他正确的事情。
EDIT 4: (Final update which was verified by the OP): Looked at the new ktpass keytab creation output, and I saw this: Targeting domain controller: WIN-OVV6VHBGIB8.fusionis.life. 编辑4 :(最终更新由OP验证):查看新的ktpass keytab创建输出,我看到了这一点:目标域控制器:WIN-OVV6VHBGIB8.fusionis.life。 Now, the defined SPN in the keytab is HTTP/kerberos500.nickis.life. 现在,keytab中定义的SPN是HTTP / kerberos500.nickis.life。 The AD domain name is different from the SPN you defined, so this is not going to work unless you have some kind of trust setup between these domains. AD域名与您定义的SPN不同,因此除非您在这些域之间建立某种信任设置,否则这不会起作用。 If you don't have a trust, you need to use an SPN of HTTP/kerberos500.fusionis.life instead. 如果您没有信任,则需要使用HTTP / kerberos500.fusionis.life的SPN。
for me, the issue is that the SPN configured is different from the url specified.对我来说,问题是配置的 SPN 与指定的 url 不同。
So let's say the SPN is HTTP/serviceX.domain.com
, when the service is accessed, it should be accessed through http://serviceX.doamin.com
, otherwise, it would throw a Defective token
error.所以假设 SPN 是HTTP/serviceX.domain.com
,访问服务时,应该通过http://serviceX.doamin.com
访问,否则会抛出Defective token
错误。
(I also found all Keberos related error messages pretty confusing, maybe MIT purposely made it difficult to understand, correspondingly would be even more difficult to hack.) (我还发现所有与 Keberos 相关的错误消息都非常混乱,也许 MIT 故意让它难以理解,相应地会更难破解。)
Try this: 试试这个:
Solution 1 解决方案1
run this on windows cmd: 在Windows cmd上运行此命令:
ksetup /addkdc ksetup /addhosttorealmmap ksetup / addkdc ksetup / addhosttorealmmap
and set SPNEGO settings on browser 并在浏览器上设置SPNEGO设置
Solution 2 解决方案2
try with Firefox, do this before: 尝试使用Firefox,之前执行此操作:
1) open this URL in Firefox 1)在Firefox中打开此URL
about:config about:config中
2) Set this: network.negotiate-auth.trusted-uris 2)设置:network.negotiate-auth.trusted-uris
Set for any cluster DNS domain requiring negotiated authentication (like the kerberos enabled cluster HTTP authentication). 为需要协商身份验证的任何群集DNS域设置(如启用kerberos的群集HTTP身份验证)。
Example: 例:
network.negotiate-auth.trusted-uris=.lily.cloudera.com,.solr.cloudera.com network.negotiate-auth.trusted-URI的= .lily.cloudera.com,.solr.cloudera.com
2) Set this: network.auth.use-sspi=false 3) Restart Firefox 4) You have to download the Windows isntaller from here: 2)设置:network.auth.use-sspi = false 3)重启Firefox 4)你必须从这里下载Windows isntaller:
http://web.mit.edu/kerberos/dist/#kfw-4.0 http://web.mit.edu/kerberos/dist/#kfw-4.0
5) Copy the Kerberos client configuration to here 5)将Kerberos客户端配置复制到此处
C:\\ProgramData\\MIT\\Kerberos5\\krb5.ini C:\\ ProgramData \\ MIT \\的Kerberos5 \\ krb5.ini
6) Create a ticket with the MIT kerberos GUI client 6)使用MIT kerberos GUI客户端创建票证
7) Try again with Firefox 7)再次尝试使用Firefox
Hope it can help. 希望它可以提供帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.