我正在尝试使用JAVA从Active Directory获取TGT进行身份验证。
这是我的代码:
try
{
URL localURL = super.getClass().getResource("jaas_ntlm_configuration.txt");
System.setProperty("java.security.auth.login.config", localURL.toString());
LoginContext localLoginContext = new LoginContext("GetLoginNameKerberos", new SampleCallbackHandler());
localLoginContext.login();
Subject localSubject = localLoginContext.getSubject();
.....
}
catch (LoginException localLoginException) {
localLoginException.printStackTrace();
}
此代码在一台服务器上运行,但在其他服务器上,它在“localLoginContext.login();”上失败。使用此输出:
>>>KinitOptions cache name is C:\Users\x\krb5cc_x
LSA: Found Ticket
LSA: Made NewWeakGlobalRef
LSA: Found PrincipalName
LSA: Made NewWeakGlobalRef
LSA: Found DerValue
LSA: Made NewWeakGlobalRef
LSA: Found EncryptionKey
LSA: Made NewWeakGlobalRef
LSA: Found TicketFlags
LSA: Made NewWeakGlobalRef
LSA: Found KerberosTime
LSA: Made NewWeakGlobalRef
LSA: Found String
LSA: Made NewWeakGlobalRef
LSA: Found DerValue constructor
LSA: Found Ticket constructor
LSA: Found PrincipalName constructor
LSA: Found EncryptionKey constructor
LSA: Found TicketFlags constructor
LSA: Found KerberosTime constructor
LSA: Finished OnLoad processing
>> Acquire default native Credentials
LSA: Found KrbCreds constructor
LSA: Got handle to Kerberos package
LSA: Response size is 1556
LSA: Principal domain is SUB.DOMAIN.COM
LSA: Name type is 1
LSA: Name count is 1
LSA: Principal domain is SUB.DOMAIN.COM
LSA: Name type is 2
LSA: Name count is 2
LSA: Session key all zero. Stop.
>>> Found no TGT's in LSA
javax.security.auth.login.LoginException: Unable to obtain Princpal Name for authentication
at com.sun.security.auth.module.Krb5LoginModule.promptForName(Unknown Source)
at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(Unknown Source)
at com.sun.security.auth.module.Krb5LoginModule.login(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at javax.security.auth.login.LoginContext.invoke(Unknown Source)
at javax.security.auth.login.LoginContext.access$000(Unknown Source)
at javax.security.auth.login.LoginContext$4.run(Unknown Source)
at javax.security.auth.login.LoginContext$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.login.LoginContext.invokePriv(Unknown Source)
at javax.security.auth.login.LoginContext.login(Unknown Source)
at my.test.MyTest.main(MyTest.java:123)
你能帮我理解是什么问题吗?
感谢。
答案 0 :(得分:6)
如果您不希望输入用户名(您希望单点登录),那么您的问题就是一个已知问题:LSA API不会移交TGT的会话密钥,因为这被认为是一个安全漏洞。错误消息清楚地表明这正是发生的事情。
有一个Windows注册表项AllowTGTSessionKey
,您可以将其设置为true以禁用此限制,但此设置是每个工作站而不是每个服务器,因此不清楚这是否是为什么它在一个地方而不是另一个地方工作。另一个原因可能是使用的Windows版本,因为这是在XP Service Pack 2中引入的,如果我没记错的话。
在Java中实现单点登录的正确方法是将TGT的处理委托给Windows SSPI,这是一种类似于GSS-API的更高级API。有一个很好的图书馆为你做这个,我个人推荐:WAFFLE。