我正在开发一个使用JAAS执行身份验证的Java应用程序,它应按以下方式工作:(i)当用户的票证uclient
已在本地缓存中时,它应在不询问凭据的情况下对用户进行身份验证;(ii)当没有“
uclient”的票证时在缓存中,它应该询问用户名/密码并将获取的票证保存到本地缓存中。
我的应用程序可以执行“ i”,但不能执行“ ii”,它可以正确验证用户身份(创建主题/主体),但是不能将Krb票据持久化到缓存中。
问题
请注意,我的应用程序必须同时在Windows AD和Linux Realms中运行。
有关我的环境和当前代码的更多数据
我正在用FreeIPA客户端和服务器配置的Linux Kerberos
Realm中测试客户端应用程序。我有一个为VMK提供AUTHDEMO.IT领域的KDC的Linux VM和一个被认可为AUTHDEMO.IT领域的Linux
VM。krb5.conf
组态:
includedir /var/lib/sss/pubconf/krb5.include.d/
[libdefaults]
default_realm = AUTHDEMO.IT
dns_lookup_realm = true
dns_lookup_kdc = true
rdns = false
ticket_lifetime = 24h
forwardable = true
udp_preference_limit = 0
default_ccache_name = KEYRING:persistent:%{uid}
[realms]
AUTHDEMO.IT = {
pkinit_anchors = FILE:/etc/ipa/ca.crt
}
[domain_realm]
.authdemo.it = AUTHDEMO.IT
authdemo.it = AUTHDEMO.IT
这是jaas.conf
针对应用程序的:
JaasDemo {
com.sun.security.auth.module.Krb5LoginModule required
useTicketCache=true
principal=uclient
debug=true;
};
我没有指定默认的缓存文件名,我在调试中验证了它的默认值: /tmp/krb5cc_1000
其中1000是运行用户的uid。
在JaasDemo类实例中,我使用以下login
方法执行身份验证:
public LoginContext login(){
LoginContext lc = null;
try {
System.out.println("Initialize logincontext");
lc = new LoginContext("JaasLogin",
new TextCallbackHandler());
} catch (LoginException | SecurityException le) {
System.err.println("Cannot create LoginContext."
+ le.getMessage());
return lc;
}
try {
// attempt authentication
System.out.println("Attempt login");
lc.login();
} catch (LoginException le) {
System.err.println("Authentication failed:");
System.err.println(" " + le.getMessage());
return lc;
}
System.out.println("Authentication succeeded!");
return lc;
}
我已经使用以下命令执行了我的应用程序(请注意详细的kerberos日志记录选项):
java -Dsun.security.krb5.debug=true -Dsun.security.jgss.debug=true -Djava.security.auth.login.config=jaas.conf -jar myapp.jar
以下是在不同情况下应用程序的输出,请注意,当询问时,用户以交互方式提供正确的凭据。 第一种情况 不存在的/tmp/krb5cc_1000
文件:
Initialize logincontext
Attempt login
Debug is true storeKey false useTicketCache true useKeyTab false doNotPrompt false ticketCache is null isInitiator true KeyTab is null refreshKrb5Config is false principal is uclient tryFirstPass is false useFirstPass is false storePass is false clearPass is false
Acquire TGT from Cache
>>>KinitOptions cache name is /tmp/krb5cc_1000
Principal is uclient@AUTHDEMO.IT
null credentials from Ticket Cache
**Login Handler invoked, providing username and password to login manager..**
[Krb5LoginModule] user entered username: uclient
Using builtin default etypes for default_tkt_enctypes
default etypes for default_tkt_enctypes: 18 17 16 23.
>>> KrbAsReq creating message
getKDCFromDNS using UDP
>>> KrbKdcReq send: kdc=authdemo2.authdemo.it. UDP:88, timeout=30000, number of retries =3, #bytes=143
>>> KDCCommunication: kdc=authdemo2.authdemo.it. UDP:88, timeout=30000,Attempt =1, #bytes=143
>>> KrbKdcReq send: #bytes read=283
>>>Pre-Authentication Data:
PA-DATA type = 136
>>>Pre-Authentication Data:
PA-DATA type = 19
PA-ETYPE-INFO2 etype = 18, salt = REMOVED 3@, s2kparams = null
PA-ETYPE-INFO2 etype = 17, salt = REMOVED, s2kparams = null
>>>Pre-Authentication Data:
PA-DATA type = 2
PA-ENC-TIMESTAMP
>>>Pre-Authentication Data:
PA-DATA type = 133
>>> KdcAccessibility: remove authdemo2.authdemo.it.:88
>>> KDCRep: init() encoding tag is 126 req type is 11
>>>KRBError:
cTime is Wed Jun 29 17:12:49 CEST 1988 583600369000
sTime is Wed Aug 02 15:53:28 CEST 2017 1501682008000
suSec is 981130
error code is 25
error Message is Additional pre-authentication required
cname is uclient@AUTHDEMO.IT
sname is krbtgt/AUTHDEMO.IT@AUTHDEMO.IT
eData provided.
msgType is 30
>>>Pre-Authentication Data:
PA-DATA type = 136
>>>Pre-Authentication Data:
PA-DATA type = 19
PA-ETYPE-INFO2 etype = 18, salt = REMOVED 3@, s2kparams = null
PA-ETYPE-INFO2 etype = 17, salt = REMOVED, s2kparams = null
>>>Pre-Authentication Data:
PA-DATA type = 2
PA-ENC-TIMESTAMP
>>>Pre-Authentication Data:
PA-DATA type = 133
KRBError received: NEEDED_PREAUTH
KrbAsReqBuilder: PREAUTH FAILED/REQ, re-send AS-REQ
Using builtin default etypes for default_tkt_enctypes
default etypes for default_tkt_enctypes: 18 17 16 23.
Using builtin default etypes for default_tkt_enctypes
default etypes for default_tkt_enctypes: 18 17 16 23.
>>> EType: sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType
>>> KrbAsReq creating message
getKDCFromDNS using UDP
>>> KrbKdcReq send: kdc=authdemo2.authdemo.it. UDP:88, timeout=30000, number of retries =3, #bytes=225
>>> KDCCommunication: kdc=authdemo2.authdemo.it. UDP:88, timeout=30000,Attempt =1, #bytes=225
>>> KrbKdcReq send: #bytes read=674
>>> KdcAccessibility: remove authdemo2.authdemo.it.:88
>>> EType: sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType
>>> KrbAsRep cons in KrbAsReq.getReply uclient
principal is uclient@AUTHDEMO.IT
Commit Succeeded
Authentication succeeded!
Subject.toString:
Principal: uclient@AUTHDEMO.IT
Private Credential: Ticket (hex) =
REMOVED TICKET DETAILS K.
Client Principal = uclient@AUTHDEMO.IT
Server Principal = krbtgt/AUTHDEMO.IT@AUTHDEMO.IT
Session Key = EncryptionKey: keyType=18 keyBytes (hex dump)=
REMOVED
Forwardable Ticket true
Forwarded Ticket false
Proxiable Ticket false
Proxy Ticket false
Postdated Ticket false
Renewable Ticket false
Initial Ticket false
Auth Time = Wed Aug 02 15:53:28 CEST 2017
Start Time = Wed Aug 02 15:53:28 CEST 2017
End Time = Thu Aug 03 15:53:28 CEST 2017
Renew Till = null
Client Addresses Null
*/tmp/krb5cc_1000
存在 *第二种情况 文件,其中包含另一个用户的票证(使用kinit
-c创建);应用程序正确进行身份验证,但获取的票证不会持久保存到缓存文件中。
klist状态优先于应用程序执行:
klist -c /tmp/krb5cc_1000
Ticket cache: FILE:/tmp/krb5cc_1000
Default principal: otheruser@AUTHDEMO.IT
Valid starting Expires Service principal
08/02/2017 16:05:19 08/03/2017 16:05:13 krbtgt/AUTHDEMO.IT@AUTHDEMO.IT
应用程序输出:
Initialize logincontext
Attempt login
Debug is true storeKey false useTicketCache true useKeyTab false doNotPrompt false ticketCache is null isInitiator true KeyTab is null refreshKrb5Config is false principal is uclient tryFirstPass is false useFirstPass is false storePass is false clearPass is false
Acquire TGT from Cache
>>>KinitOptions cache name is /tmp/krb5cc_1000
java.io.IOException: Primary principals don't match.
at sun.security.krb5.internal.ccache.FileCredentialsCache.load(FileCredentialsCache.java:179)
at sun.security.krb5.internal.ccache.FileCredentialsCache.acquireInstance(FileCredentialsCache.java:82)
at sun.security.krb5.internal.ccache.CredentialsCache.getInstance(CredentialsCache.java:83)
at sun.security.krb5.Credentials.acquireTGTFromCache(Credentials.java:333)
at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(Krb5LoginModule.java:665)
at com.sun.security.auth.module.Krb5LoginModule.login(Krb5LoginModule.java:617)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at javax.security.auth.login.LoginContext.invoke(LoginContext.java:755)
at javax.security.auth.login.LoginContext.access$000(LoginContext.java:195)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:682)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:680)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:680)
at javax.security.auth.login.LoginContext.login(LoginContext.java:587)
at it.kerberosdemo.login.JaasDemo.login(JaasDemo.java:45)
at it.kerberosdemo.login.JaasDemo.login(JaasDemo.java:27)
at it.male.kerberosdemo.client.ClientMain.main(ClientMain.java:29)
Principal is uclient@AUTHDEMO.IT
null credentials from Ticket Cache
Login Handler invokerd, providing username and password to login manager..
[Krb5LoginModule] user entered username: uclient
Using builtin default etypes for default_tkt_enctypes
default etypes for default_tkt_enctypes: 18 17 16 23.
>>> KrbAsReq creating message
getKDCFromDNS using UDP
>>> KrbKdcReq send: kdc=authdemo2.authdemo.it. UDP:88, timeout=30000, number of retries =3, #bytes=143
>>> KDCCommunication: kdc=authdemo2.authdemo.it. UDP:88, timeout=30000,Attempt =1, #bytes=143
>>> KrbKdcReq send: #bytes read=283
>>>Pre-Authentication Data:
PA-DATA type = 136
>>>Pre-Authentication Data:
PA-DATA type = 19
PA-ETYPE-INFO2 etype = 18, salt = REMOVED, s2kparams = null
PA-ETYPE-INFO2 etype = 17, salt = REMOVED, s2kparams = null
>>>Pre-Authentication Data:
PA-DATA type = 2
PA-ENC-TIMESTAMP
>>>Pre-Authentication Data:
PA-DATA type = 133
>>> KdcAccessibility: remove authdemo2.authdemo.it.:88
>>> KDCRep: init() encoding tag is 126 req type is 11
>>>KRBError:
cTime is Mon Sep 22 16:38:56 CEST 2031 1947854336000
sTime is Wed Aug 02 16:07:05 CEST 2017 1501682825000
suSec is 803283
error code is 25
error Message is Additional pre-authentication required
cname is uclient@AUTHDEMO.IT
sname is krbtgt/AUTHDEMO.IT@AUTHDEMO.IT
eData provided.
msgType is 30
>>>Pre-Authentication Data:
PA-DATA type = 136
...OMITTED IDENTICAL
klist确认没有为“ uclient”添加任何票证到高速缓存文件中。
问候
最后我找到了问题1 + 2的答案
kinit
与Java发行版捆绑在一起的命令是一个Java应用程序,该应用程序对用户进行身份验证进入领域/域,并将获取的票证保存在ccache
文件中。该kinit
命令代码sun.security.krb5.internal.tools
在OpenJDK
的软件包中可用。主要的课程是sun.security.krb5.internal.tools.Kinit
。为了获取(认证)并保留Kerberos票证,您可以将所有tool
包复制到应用程序中,并通过提供cli参数从Kinit
类中调用该方法main(String[] arv)
。您也可以像我一样更改Kinit
类,以更好地与您的代码集成。
Kinit
代码对于理解内部专用Kerberos代码的内部工作方式以及对其进行自定义非常有用。例如,有一个KDCOptions
您可以手动配置的实例,以索取可再生票证等等。让我们学习吧!;-)
请考虑:
我可以确认我的代码在OpenJDK和Oracle JDK上都能正常工作。
大图
目前,我的应用程序使用Jaas来通过查看本地ccache
文件中的Krb凭证进行身份验证,如果失败,它将执行上述kinit
代码。然后,它使用更新ccache
文件中的Jaas进行身份验证。
下一步
我目前正在尝试将Kerberos票证直接从主题对象中的凭据持久保存到ccache。
我将尝试使用sun.security.krb5.internal.ccache.FileCredentialCache
该类,但它看起来很底层。让我们看看在CredentialCache
kinit代码中使用抽象类,可能有用。如果成功,我将更新线程。
谢谢
谢谢Michael-O向我展示了sun.security.krb5.internal
最终找到kinit
代码的软件包。
问候
我正在开发一个用JAAS进行身份验证的Java应用程序,应该如下工作:(I)当用户的票证已经在本地缓存中时,它应该在不询问凭据的情况下对用户进行身份验证,(ii)当缓存中没有“uclient”的票证时,它应该请求用户名/密码,并将获取的票证保存到本地缓存中。 我的应用程序能够执行“i”,但不能执行“ii”,它正确地验证用户(创建主题/主体),但不会将Krb票证持久保存到缓存中。 问题 我如何实现/
我试图在使用JGit拉取回购时使用Kerberos身份验证,但出现以下错误: 来自Ticket Cache的空凭据 [Krb5LoginMoules]身份验证失败 这是我的登录名。形态 我使用自定义的JcshConfigSessionFactory和重写配置方法,如下所示 “klist”说凭证缓存是API(我在MacOS Sierra上)。我怎样才能克服这次失败?
我正在使用一个keytab,并使用windows命令行上的kinit命令设置它。我得到消息“new ticket is storage in cache file”。之后,当我运行java应用程序访问keytab文件以获取密钥时,我得到以下错误。 C:\users\cxxxxx\git\abcd.keytab refreshKrb5Config为false主体为xxxx_dev@xxxx.xxxx
我们的hadoop集群使用kerberos,所以我们需要先使用kinit,然后使用类似“hadoop fs-ls/”的命令。现在我使用jaas和gssapi登录并在集群中创建文件,但失败了。这是我的代码: 贾斯。具体如下: 我的登录用户名是root,在使用“hadoop jar./client.jar”之前运行此代码,我运行kdestory删除kerberos缓存,然后我得到以下错误: 我不知道如
和RDD相似,DStreams也允许开发者持久化流数据到内存中。在DStream上使用persist()方法可以自动地持久化DStream中的RDD到内存中。如果DStream中的数据需要计算多次,这是非常有用的。像reduceByWindow和reduceByKeyAndWindow这种窗口操作、updateStateByKey这种基于状态的操作,持久化是默认的,不需要开发者调用persist(
问题内容: 在我的服务器应用程序中,我正在从Java应用程序连接到受Kerberos保护的Hadoop群集。在应用程序启动时,我会打电话给 我正在使用本机API(例如和)进行基本的File操作 我的应用程序在24小时后引发以下错误。这就是Kerberos票证的到期日。 我的应用程序使用Java 8,并且遇到了此错误。 但是,看起来我的应用程序使用的hadoop- common-2.7.1.2.4.