使用带委托的 Kerberos 时,GSS API 和 SSPI API 有什么区别?
What is the difference between GSS API and SSPI API when using Kerberos with delegation?
使用带委托的 Kerberos 时,GSS API 和 SSPI API 有什么区别?
我在 Tomcat 服务器中有中间件 运行 Java 代码。
中间件使用 Kerberos (GSS API) 对用户进行身份验证。如果授权 header 中不存在 Kerberos 令牌,中间件 returns 401 并附加 WWW-Authenticate:协商响应 header 以初始化 SPNEGO 身份验证。
使用 GSSContext.acceptSecContext 检查传入的服务票据工作正常。
但是,我在授权案例中遇到了一些问题。
正如名称“中间件”所示,我的 java 服务必须使用原始用户主体使用 Kerberos 身份验证来调用后端服务。为此,我实施了 Kerberos Java GSS API 委托机制。此外,AD 配置正确,tomcat 作为具有特定服务帐户的服务运行。
为了测试此实现,我编写了一个 Java 测试客户端,利用 GSS API 获取中间件的票证。 运行 Java 具有管理员权限的测试客户端或使用 kinit -f 客户端和中间件组合获得可转发的票证工作正常:
客户端获得票证,中间件接受票证,GSSContext.getCredDelegState() returns true,使用 GSSContext.getDelegCred() 中间件获得委托凭据并且后端登录正常。
此外,我还使用浏览器和一个小型 C# 测试客户端测试了中间件的实现。两者都使用 SPNEGO。在这种情况下,授权也有效。我收到身份验证成功的消息,并且我获得了用户 Principal。
使用浏览器或我的 C# 测试客户端,我在中间件中得到以下调试打印:
Debug is true storeKey true useTicketCache false useKeyTab true doNotPrompt false ticketCache is null isInitiator false KeyTab is D:/app/Tomcat_9019_SSO/conf/tomcat.keytab refreshKrb5Config is true principal is HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET tryFirstPass is false useFirstPass is false storePass is false clearPass is false
Refreshing Kerberos configuration
Java config name: C:\Windows\kerb5.ini
Loading krb5 profile at C:\Windows\kerb5.ini
Loaded from Java config
>>> KdcAccessibility: reset
principal is HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET
Will use keytab
Commit Succeeded
2020-03-18 06:36:50.254 INFO .e.s.a.t.a.KerberosCheckAuthTicketAction [TC~3~c80e3d5b-3] : Starting check of incoming Kerberos service ticket.
Search Subject for SPNEGO ACCEPT cred (<<DEF>>, sun.security.jgss.spnego.SpNegoCredElement)
Search Subject for Kerberos V5 ACCEPT cred (<<DEF>>, sun.security.jgss.krb5.Krb5AcceptCredential)
Found KeyTab D:\app\Tomcat_9019_SSO\conf\tomcat.keytab for HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET
Found KeyTab D:\app\Tomcat_9019_SSO\conf\tomcat.keytab for HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET
Search Subject for Kerberos V5 ACCEPT cred (<<DEF>>, sun.security.jgss.krb5.Krb5AcceptCredential)
Found KeyTab D:\app\Tomcat_9019_SSO\conf\tomcat.keytab for HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET
Found KeyTab D:\app\Tomcat_9019_SSO\conf\tomcat.keytab for HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET
Entered Krb5Context.acceptSecContext with state=STATE_NEW
Looking for keys for: HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET
Added key: 23version: 0
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
Using builtin default etypes for permitted_enctypes
default etypes for permitted_enctypes: 18 17 20 19 16 23.
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
MemoryCache: add 1584509810/000627/5EBDF35F49476E365F32DE53C3CAFA81C4730A13D881ECA15E9F43023F99A80B/CLIENTUSERD@MYDOMAIN.NET to CLIENTUSERD@MYDOMAIN.NET|HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET
>>> KrbApReq: authenticate succeed.
Krb5Context setting peerSeqNumber to: 947381056
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
Krb5Context setting mySeqNumber to: 214468704
>>> Constrained deleg from GSSCaller{UNKNOWN}
Debug is true storeKey true useTicketCache false useKeyTab true doNotPrompt false ticketCache is null isInitiator true KeyTab is D:/app/Tomcat_9019_SSO/conf/tomcat.keytab refreshKrb5Config is false principal is HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET tryFirstPass is false useFirstPass is false storePass is false clearPass is false
Looking for keys for: HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET
Added key: 23version: 0
Looking for keys for: HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET
Added key: 23version: 0
default etypes for default_tkt_enctypes: 23 18 17.
>>> KrbAsReq creating message
>>> KrbKdcReq send: kdc=kb01.mydomain.net UDP:88, timeout=30000, number of retries =3, #bytes=174
>>> KDCCommunication: kdc=kb01.mydomain.net UDP:88, timeout=30000,Attempt =1, #bytes=174
>>> KrbKdcReq send: #bytes read=175
>>>Pre-Authentication Data:
PA-DATA type = 11
PA-ETYPE-INFO etype = 23, salt =
>>>Pre-Authentication Data:
PA-DATA type = 19
PA-ETYPE-INFO2 etype = 23, salt = null, s2kparams = null
>>>Pre-Authentication Data:
PA-DATA type = 2
PA-ENC-TIMESTAMP
>>>Pre-Authentication Data:
PA-DATA type = 16
>>>Pre-Authentication Data:
PA-DATA type = 15
>>> KdcAccessibility: remove kb01.mydomain.net
>>> KDCRep: init() encoding tag is 126 req type is 11
>>>KRBError:
sTime is Wed Mar 18 06:36:50 CET 2020 1584509810000
suSec is 765149
error code is 25
error Message is Additional pre-authentication required
sname is krbtgt/MYDOMAIN.NET@MYDOMAIN.NET
eData provided.
msgType is 30
>>>Pre-Authentication Data:
PA-DATA type = 11
PA-ETYPE-INFO etype = 23, salt =
>>>Pre-Authentication Data:
PA-DATA type = 19
PA-ETYPE-INFO2 etype = 23, salt = null, s2kparams = null
>>>Pre-Authentication Data:
PA-DATA type = 2
PA-ENC-TIMESTAMP
>>>Pre-Authentication Data:
PA-DATA type = 16
>>>Pre-Authentication Data:
PA-DATA type = 15
KrbAsReqBuilder: PREAUTH FAILED/REQ, re-send AS-REQ
default etypes for default_tkt_enctypes: 23 18 17.
Looking for keys for: HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET
Added key: 23version: 0
Looking for keys for: HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET
Added key: 23version: 0
default etypes for default_tkt_enctypes: 23 18 17.
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
>>> KrbAsReq creating message
>>> KrbKdcReq send: kdc=kb01.mydomain.net UDP:88, timeout=30000, number of retries =3, #bytes=253
>>> KDCCommunication: kdc=kb01.mydomain.net UDP:88, timeout=30000,Attempt =1, #bytes=253
>>> KrbKdcReq send: #bytes read=90
>>> KrbKdcReq send: kdc=kb01.mydomain.net TCP:88, timeout=30000, number of retries =3, #bytes=253
>>> KDCCommunication: kdc=kb01.mydomain.net TCP:88, timeout=30000,Attempt =1, #bytes=253
>>>DEBUG: TCPClient reading 2154 bytes
>>> KrbKdcReq send: #bytes read=2154
>>> KdcAccessibility: remove kb01.mydomain.net
Looking for keys for: HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET
Added key: 23version: 0
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
[Krb5LoginModule] authentication failed
Message stream modified (41)
使用 Java 客户端,我在中间件中得到这个调试打印:
Debug is true storeKey true useTicketCache false useKeyTab true doNotPrompt false ticketCache is null isInitiator false KeyTab is D:/app/Tomcat_9019_SSO/conf/tomcat.keytab refreshKrb5Config is true principal is HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET tryFirstPass is false useFirstPass is false storePass is false clearPass is false
Refreshing Kerberos configuration
Java config name: C:\Windows\kerb5.ini
Loading krb5 profile at C:\Windows\kerb5.ini
Loaded from Java config
>>> KdcAccessibility: reset
principal is HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET
Will use keytab
Commit Succeeded
2020-03-18 06:47:41.029 INFO .e.s.a.t.a.KerberosCheckAuthTicketAction [TC~9~c80e3d5b-9] : Starting check of incoming Kerberos service ticket.
Search Subject for SPNEGO ACCEPT cred (<<DEF>>, sun.security.jgss.spnego.SpNegoCredElement)
Search Subject for Kerberos V5 ACCEPT cred (<<DEF>>, sun.security.jgss.krb5.Krb5AcceptCredential)
Found KeyTab D:\app\Tomcat_9019_SSO\conf\tomcat.keytab for HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET
Found KeyTab D:\app\Tomcat_9019_SSO\conf\tomcat.keytab for HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET
Search Subject for Kerberos V5 ACCEPT cred (<<DEF>>, sun.security.jgss.krb5.Krb5AcceptCredential)
Found KeyTab D:\app\Tomcat_9019_SSO\conf\tomcat.keytab for HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET
Found KeyTab D:\app\Tomcat_9019_SSO\conf\tomcat.keytab for HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET
Entered Krb5Context.acceptSecContext with state=STATE_NEW
Looking for keys for: HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET
Added key: 23version: 0
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
Using builtin default etypes for permitted_enctypes
default etypes for permitted_enctypes: 18 17 20 19 16 23.
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
MemoryCache: add 1584510459/567826/FDE0027391B8BF26BF807FF04E5FD5F7CE38794A3264EB298BB36F736B2CF050/CLIENTUSERD@MYDOMAIN.NET to CLIENTUSERD@MYDOMAIN.NET|HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET
>>> KrbApReq: authenticate succeed.
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
>>>Delegated Creds have pname=CLIENTUSERD@MYDOMAIN.NET sname=krbtgt/MYDOMAIN.NET@MYDOMAIN.NET authtime=20200318054735Z starttime=20200318054739Z endtime=20200318154735ZrenewTill=null
Krb5Context setting peerSeqNumber to: 99984043
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
Krb5Context setting mySeqNumber to: 161819208
但是,这里的主要问题是,在 Java 客户端的情况下,委托有效,而在浏览器和 C# 客户端的情况下,委托不起作用。
请注意,浏览器已配置为将要委派的域列入白名单。
附加信息:
我配置了约束委派。 Tomcat 与中间件是 运行 在 Windows 2016 服务器作为具有 AD 服务帐户的服务。
我比较了发送到中间件的服务票:
Java(可转发),委托工作:
10980 字节
C#(委托不起作用):
8572 字节
浏览器(委托不起作用):
8572 字节
为了比较,我使用了不带 -f 选项的 kinit 来获取不可转发的 tgt 并测量了大小:
Java(不可转发,委托不起作用):
8174 字节
顺便说一句,这会产生同样的错误。
AD中的中间件服务账号是如何配置委托的?不受约束还是受约束?
尝试获取 java 和 C# 客户端发送的票证副本并比较票证大小。它们应该大致相同,但是如果一个明显更大,那么更大的包含一个委托的 TGT。
根据日志,Java 客户端似乎正在发送不受约束的票证(委托的 TGT,又名转发)并且正在使用它。
我们看不到 C# 票证包含的内容,但中间件在收到后立即尝试联系 KDC,这似乎表明它可能试图将其交换为委托票证,但失败了,因为中间件不能'不要先拿到自己的票。这是一个有点疯狂的猜测,因为日志没有以某种方式表明它启动 AS-REQ 的原因。
您可能会考虑获取 中间件和 KDC 之间的网络跟踪,以查看它在 C# 案例中发送的内容。
这是我自己问题的答案。
我意识到我工作的域有 3 个域控制器:
在我的中间件中,krb5.ini 配置了第一个:
[realms]
MYDOMAIN.NET = {
kdc = d01.mydomain.net
admin_server = d01.mydomain.net
default_domain = MYDOMAIN.NET
}
我的 Java 测试客户端有以下代码行
System.setProperty("java.security.krb5.kdc", d01.mydomain.net);
但是,我的客户端计算机使用了 d02.mydomain.net 我在使用“klist”命令时看到的内容。
#2> Client: CLIENTUSERD @ MYDOMAIN.NET
Server: HTTP/SERVICE.MYDOMAIN.NET @ MYDOMAIN.NET
KerbTicket Encryption Type: RSADSI RC4-HMAC(NT)
Ticket Flags 0x40a00000 -> forwardable renewable pre_authent
Start Time: 3/24/2020 5:33:39 (local)
End Time: 3/24/2020 15:33:39 (local)
Renew Time: 3/31/2020 5:33:39 (local)
Session Key Type: RSADSI RC4-HMAC(NT)
Cache Flags: 0
Kdc Called: d02.mydomain.net
出于某些原因——我现在还不清楚——如果错误的域控制器必须协同工作,则委派不起作用。
如果我在中间件中将域控制器更改为 d03.mydomain.net,委托工作正常。
但是,门票接受在任何组合中都可以正常工作。
可能是域控制器的时间不同步。
使用带委托的 Kerberos 时,GSS API 和 SSPI API 有什么区别?
我在 Tomcat 服务器中有中间件 运行 Java 代码。 中间件使用 Kerberos (GSS API) 对用户进行身份验证。如果授权 header 中不存在 Kerberos 令牌,中间件 returns 401 并附加 WWW-Authenticate:协商响应 header 以初始化 SPNEGO 身份验证。
使用 GSSContext.acceptSecContext 检查传入的服务票据工作正常。
但是,我在授权案例中遇到了一些问题。
正如名称“中间件”所示,我的 java 服务必须使用原始用户主体使用 Kerberos 身份验证来调用后端服务。为此,我实施了 Kerberos Java GSS API 委托机制。此外,AD 配置正确,tomcat 作为具有特定服务帐户的服务运行。
为了测试此实现,我编写了一个 Java 测试客户端,利用 GSS API 获取中间件的票证。 运行 Java 具有管理员权限的测试客户端或使用 kinit -f 客户端和中间件组合获得可转发的票证工作正常: 客户端获得票证,中间件接受票证,GSSContext.getCredDelegState() returns true,使用 GSSContext.getDelegCred() 中间件获得委托凭据并且后端登录正常。
此外,我还使用浏览器和一个小型 C# 测试客户端测试了中间件的实现。两者都使用 SPNEGO。在这种情况下,授权也有效。我收到身份验证成功的消息,并且我获得了用户 Principal。 使用浏览器或我的 C# 测试客户端,我在中间件中得到以下调试打印:
Debug is true storeKey true useTicketCache false useKeyTab true doNotPrompt false ticketCache is null isInitiator false KeyTab is D:/app/Tomcat_9019_SSO/conf/tomcat.keytab refreshKrb5Config is true principal is HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET tryFirstPass is false useFirstPass is false storePass is false clearPass is false
Refreshing Kerberos configuration
Java config name: C:\Windows\kerb5.ini
Loading krb5 profile at C:\Windows\kerb5.ini
Loaded from Java config
>>> KdcAccessibility: reset
principal is HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET
Will use keytab
Commit Succeeded
2020-03-18 06:36:50.254 INFO .e.s.a.t.a.KerberosCheckAuthTicketAction [TC~3~c80e3d5b-3] : Starting check of incoming Kerberos service ticket.
Search Subject for SPNEGO ACCEPT cred (<<DEF>>, sun.security.jgss.spnego.SpNegoCredElement)
Search Subject for Kerberos V5 ACCEPT cred (<<DEF>>, sun.security.jgss.krb5.Krb5AcceptCredential)
Found KeyTab D:\app\Tomcat_9019_SSO\conf\tomcat.keytab for HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET
Found KeyTab D:\app\Tomcat_9019_SSO\conf\tomcat.keytab for HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET
Search Subject for Kerberos V5 ACCEPT cred (<<DEF>>, sun.security.jgss.krb5.Krb5AcceptCredential)
Found KeyTab D:\app\Tomcat_9019_SSO\conf\tomcat.keytab for HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET
Found KeyTab D:\app\Tomcat_9019_SSO\conf\tomcat.keytab for HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET
Entered Krb5Context.acceptSecContext with state=STATE_NEW
Looking for keys for: HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET
Added key: 23version: 0
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
Using builtin default etypes for permitted_enctypes
default etypes for permitted_enctypes: 18 17 20 19 16 23.
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
MemoryCache: add 1584509810/000627/5EBDF35F49476E365F32DE53C3CAFA81C4730A13D881ECA15E9F43023F99A80B/CLIENTUSERD@MYDOMAIN.NET to CLIENTUSERD@MYDOMAIN.NET|HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET
>>> KrbApReq: authenticate succeed.
Krb5Context setting peerSeqNumber to: 947381056
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
Krb5Context setting mySeqNumber to: 214468704
>>> Constrained deleg from GSSCaller{UNKNOWN}
Debug is true storeKey true useTicketCache false useKeyTab true doNotPrompt false ticketCache is null isInitiator true KeyTab is D:/app/Tomcat_9019_SSO/conf/tomcat.keytab refreshKrb5Config is false principal is HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET tryFirstPass is false useFirstPass is false storePass is false clearPass is false
Looking for keys for: HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET
Added key: 23version: 0
Looking for keys for: HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET
Added key: 23version: 0
default etypes for default_tkt_enctypes: 23 18 17.
>>> KrbAsReq creating message
>>> KrbKdcReq send: kdc=kb01.mydomain.net UDP:88, timeout=30000, number of retries =3, #bytes=174
>>> KDCCommunication: kdc=kb01.mydomain.net UDP:88, timeout=30000,Attempt =1, #bytes=174
>>> KrbKdcReq send: #bytes read=175
>>>Pre-Authentication Data:
PA-DATA type = 11
PA-ETYPE-INFO etype = 23, salt =
>>>Pre-Authentication Data:
PA-DATA type = 19
PA-ETYPE-INFO2 etype = 23, salt = null, s2kparams = null
>>>Pre-Authentication Data:
PA-DATA type = 2
PA-ENC-TIMESTAMP
>>>Pre-Authentication Data:
PA-DATA type = 16
>>>Pre-Authentication Data:
PA-DATA type = 15
>>> KdcAccessibility: remove kb01.mydomain.net
>>> KDCRep: init() encoding tag is 126 req type is 11
>>>KRBError:
sTime is Wed Mar 18 06:36:50 CET 2020 1584509810000
suSec is 765149
error code is 25
error Message is Additional pre-authentication required
sname is krbtgt/MYDOMAIN.NET@MYDOMAIN.NET
eData provided.
msgType is 30
>>>Pre-Authentication Data:
PA-DATA type = 11
PA-ETYPE-INFO etype = 23, salt =
>>>Pre-Authentication Data:
PA-DATA type = 19
PA-ETYPE-INFO2 etype = 23, salt = null, s2kparams = null
>>>Pre-Authentication Data:
PA-DATA type = 2
PA-ENC-TIMESTAMP
>>>Pre-Authentication Data:
PA-DATA type = 16
>>>Pre-Authentication Data:
PA-DATA type = 15
KrbAsReqBuilder: PREAUTH FAILED/REQ, re-send AS-REQ
default etypes for default_tkt_enctypes: 23 18 17.
Looking for keys for: HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET
Added key: 23version: 0
Looking for keys for: HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET
Added key: 23version: 0
default etypes for default_tkt_enctypes: 23 18 17.
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
>>> KrbAsReq creating message
>>> KrbKdcReq send: kdc=kb01.mydomain.net UDP:88, timeout=30000, number of retries =3, #bytes=253
>>> KDCCommunication: kdc=kb01.mydomain.net UDP:88, timeout=30000,Attempt =1, #bytes=253
>>> KrbKdcReq send: #bytes read=90
>>> KrbKdcReq send: kdc=kb01.mydomain.net TCP:88, timeout=30000, number of retries =3, #bytes=253
>>> KDCCommunication: kdc=kb01.mydomain.net TCP:88, timeout=30000,Attempt =1, #bytes=253
>>>DEBUG: TCPClient reading 2154 bytes
>>> KrbKdcReq send: #bytes read=2154
>>> KdcAccessibility: remove kb01.mydomain.net
Looking for keys for: HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET
Added key: 23version: 0
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
[Krb5LoginModule] authentication failed
Message stream modified (41)
使用 Java 客户端,我在中间件中得到这个调试打印:
Debug is true storeKey true useTicketCache false useKeyTab true doNotPrompt false ticketCache is null isInitiator false KeyTab is D:/app/Tomcat_9019_SSO/conf/tomcat.keytab refreshKrb5Config is true principal is HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET tryFirstPass is false useFirstPass is false storePass is false clearPass is false
Refreshing Kerberos configuration
Java config name: C:\Windows\kerb5.ini
Loading krb5 profile at C:\Windows\kerb5.ini
Loaded from Java config
>>> KdcAccessibility: reset
principal is HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET
Will use keytab
Commit Succeeded
2020-03-18 06:47:41.029 INFO .e.s.a.t.a.KerberosCheckAuthTicketAction [TC~9~c80e3d5b-9] : Starting check of incoming Kerberos service ticket.
Search Subject for SPNEGO ACCEPT cred (<<DEF>>, sun.security.jgss.spnego.SpNegoCredElement)
Search Subject for Kerberos V5 ACCEPT cred (<<DEF>>, sun.security.jgss.krb5.Krb5AcceptCredential)
Found KeyTab D:\app\Tomcat_9019_SSO\conf\tomcat.keytab for HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET
Found KeyTab D:\app\Tomcat_9019_SSO\conf\tomcat.keytab for HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET
Search Subject for Kerberos V5 ACCEPT cred (<<DEF>>, sun.security.jgss.krb5.Krb5AcceptCredential)
Found KeyTab D:\app\Tomcat_9019_SSO\conf\tomcat.keytab for HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET
Found KeyTab D:\app\Tomcat_9019_SSO\conf\tomcat.keytab for HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET
Entered Krb5Context.acceptSecContext with state=STATE_NEW
Looking for keys for: HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET
Added key: 23version: 0
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
Using builtin default etypes for permitted_enctypes
default etypes for permitted_enctypes: 18 17 20 19 16 23.
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
MemoryCache: add 1584510459/567826/FDE0027391B8BF26BF807FF04E5FD5F7CE38794A3264EB298BB36F736B2CF050/CLIENTUSERD@MYDOMAIN.NET to CLIENTUSERD@MYDOMAIN.NET|HTTP/SERVICE.MYDOMAIN.NET@MYDOMAIN.NET
>>> KrbApReq: authenticate succeed.
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
>>>Delegated Creds have pname=CLIENTUSERD@MYDOMAIN.NET sname=krbtgt/MYDOMAIN.NET@MYDOMAIN.NET authtime=20200318054735Z starttime=20200318054739Z endtime=20200318154735ZrenewTill=null
Krb5Context setting peerSeqNumber to: 99984043
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
Krb5Context setting mySeqNumber to: 161819208
但是,这里的主要问题是,在 Java 客户端的情况下,委托有效,而在浏览器和 C# 客户端的情况下,委托不起作用。 请注意,浏览器已配置为将要委派的域列入白名单。
附加信息: 我配置了约束委派。 Tomcat 与中间件是 运行 在 Windows 2016 服务器作为具有 AD 服务帐户的服务。
我比较了发送到中间件的服务票:
Java(可转发),委托工作: 10980 字节
C#(委托不起作用): 8572 字节
浏览器(委托不起作用): 8572 字节
为了比较,我使用了不带 -f 选项的 kinit 来获取不可转发的 tgt 并测量了大小:
Java(不可转发,委托不起作用): 8174 字节
顺便说一句,这会产生同样的错误。
AD中的中间件服务账号是如何配置委托的?不受约束还是受约束?
尝试获取 java 和 C# 客户端发送的票证副本并比较票证大小。它们应该大致相同,但是如果一个明显更大,那么更大的包含一个委托的 TGT。
根据日志,Java 客户端似乎正在发送不受约束的票证(委托的 TGT,又名转发)并且正在使用它。
我们看不到 C# 票证包含的内容,但中间件在收到后立即尝试联系 KDC,这似乎表明它可能试图将其交换为委托票证,但失败了,因为中间件不能'不要先拿到自己的票。这是一个有点疯狂的猜测,因为日志没有以某种方式表明它启动 AS-REQ 的原因。
您可能会考虑获取 中间件和 KDC 之间的网络跟踪,以查看它在 C# 案例中发送的内容。
这是我自己问题的答案。
我意识到我工作的域有 3 个域控制器: 在我的中间件中,krb5.ini 配置了第一个:
[realms]
MYDOMAIN.NET = {
kdc = d01.mydomain.net
admin_server = d01.mydomain.net
default_domain = MYDOMAIN.NET
}
我的 Java 测试客户端有以下代码行
System.setProperty("java.security.krb5.kdc", d01.mydomain.net);
但是,我的客户端计算机使用了 d02.mydomain.net 我在使用“klist”命令时看到的内容。
#2> Client: CLIENTUSERD @ MYDOMAIN.NET
Server: HTTP/SERVICE.MYDOMAIN.NET @ MYDOMAIN.NET
KerbTicket Encryption Type: RSADSI RC4-HMAC(NT)
Ticket Flags 0x40a00000 -> forwardable renewable pre_authent
Start Time: 3/24/2020 5:33:39 (local)
End Time: 3/24/2020 15:33:39 (local)
Renew Time: 3/31/2020 5:33:39 (local)
Session Key Type: RSADSI RC4-HMAC(NT)
Cache Flags: 0
Kdc Called: d02.mydomain.net
出于某些原因——我现在还不清楚——如果错误的域控制器必须协同工作,则委派不起作用。 如果我在中间件中将域控制器更改为 d03.mydomain.net,委托工作正常。 但是,门票接受在任何组合中都可以正常工作。 可能是域控制器的时间不同步。