当前位置: 首页 > 知识库问答 >
问题:

JAAS-无法将Kerberos票持久化到缓存文件,并且无法从头开始创建缓存...

百里默
2023-03-14

我正在开发一个用JAAS进行身份验证的Java应用程序,应该如下工作:(I)当用户uclient的票证已经在本地缓存中时,它应该在不询问凭据的情况下对用户进行身份验证,(ii)当缓存中没有“uclient”的票证时,它应该请求用户名/密码,并将获取的票证保存到本地缓存中。

我的应用程序能够执行“i”,但不能执行“ii”,它正确地验证用户(创建主题/主体),但不会将Krb票证持久保存到缓存中。

问题

  1. 我如何实现/实施这一点

请注意,我的应用程序必须在Windows AD和Linux领域工作。

更多关于我的环境和当前代码的数据

我测试客户端应用程序在LinuxKerberos领域配置FreeIPA客户端和服务器。我有一个LinuxVM,它为AUTHDEMO. IT领域提供KDC,还有一个Linux VM,它被认可到AUTHDEMO. IT领域。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类实例中,我使用以下方法执行身份验证:

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”的票证添加到缓存文件中。

当做

共有3个答案

洪和平
2023-03-14

其他问题。

3-只是出于好奇,JavaJaaS能够管理linux KEYRINGs吗?(目前Jaas无法自动管理它们)

不,内部Java Krb类只管理文件,而不是密钥环。

4-JavaJaaS只能管理/保留缓存中默认主体的票证吗?-或者我如何使用JaaS管理在单个缓存文件中有大量主体票证的情况?

我发现没有简单的方法来管理集合(这是一个相当新的标准),我个人的选择是为每个主体创建一个缓存文件。

弘康安
2023-03-14

不能。Java不支持将TGT或服务票证持久化回可与MIT Kerberos或Heimdal一起使用的基于文件的缓存。Oracle有一些私有类来做这件事,但我不建议这样做。

戴原
2023-03-14

最后我找到了问题12的答案

与java发行版捆绑在一起的kinit命令是一个java应用程序,它可以验证用户进入领域/域的身份,并将获取的票据保存在ccache文件中。kinit命令代码可在sun中找到。安全krb5。内部的OpenJDK的工具包。主类是sun。安全krb5。内部的工具。Kinit。为了获取(验证)并保存Kerberos票证,您可以将所有工具包复制到应用程序中,并通过提供cli参数从Kinit类调用方法main(String[]arv)。您还可以像我所做的那样,更改Kinit类,以便更好地与代码集成。

Kinit代码对于理解内部私有Kerberos代码的内部工作原理和自定义代码非常有用。例如,您可以手动配置一个KDCOments实例,以便请求可再生票据等。我们来研究一下吧!;-)

请考虑:

  • 无法保证内部代码的接口在未来的JDK版本中保持不变

我可以确认我的代码在OpenJDK和Oracle JDK上都运行良好。

大局

目前,我的应用程序使用Jaas,以便通过查看本地cache文件中的Krb凭据进行身份验证,如果失败,它将执行上面提到的kinit代码。然后,它使用Jaas从更新的cache文件进行身份验证。

下一步

我目前试图持久化KerberosTicket直接从主题对象中的凭据缓存。
我将尝试使用sun.security.krb5.internal.ccache.文件凭据缓存类,但它看起来是一种低级的方法。让我们来看看在kinit代码中使用CreentialCache抽象类,可能是有用的。如果成功,我会更新线程

谢啦

感谢Michael-O为我展示了太阳。安全krb5。内部软件包,我终于找到了kinit代码。

当做

 类似资料:
  • 问题内容: 我正在开发一个使用JAAS执行身份验证的Java应用程序,它应按以下方式工作:(i)当用户的票证已在本地缓存中时,它应在不询问凭据的情况下对用户进行身份验证;(ii)当没有“ uclient”的票证时在缓存中,它应该询问用户名/密码并将获取的票证保存到本地缓存中。 我的应用程序可以执行“ i”,但不能执行“ ii”,它可以正确验证用户身份(创建主题/主体),但是不能将Krb票据持久化到

  • 我试图在使用JGit拉取回购时使用Kerberos身份验证,但出现以下错误: 来自Ticket Cache的空凭据 [Krb5LoginMoules]身份验证失败 这是我的登录名。形态 我使用自定义的JcshConfigSessionFactory和重写配置方法,如下所示 “klist”说凭证缓存是API(我在MacOS Sierra上)。我怎样才能克服这次失败?

  • 和RDD相似,DStreams也允许开发者持久化流数据到内存中。在DStream上使用persist()方法可以自动地持久化DStream中的RDD到内存中。如果DStream中的数据需要计算多次,这是非常有用的。像reduceByWindow和reduceByKeyAndWindow这种窗口操作、updateStateByKey这种基于状态的操作,持久化是默认的,不需要开发者调用persist(

  • 我在做计算器(顺便说一句,我是个初学者)。我几乎完成了它,直到我需要格式化我的电脑,并且在第一次重新打开Android Studio之后,它才打开,但现在它没有打开,并且显示了这个例外: 失败:生成失败,出现异常。 哪里出了问题: 无法打开a4fwtlbt6cgvdv2n0389t2u6w的cp\U初始化重新映射类缓存(C:\Users\tambe.gradle\caches\6.1.1\scri

  • 错误:无法为初始化脚本'C:\User\Avishek\AppData\Local\Temp\asLocalRepo14.gradle'打开initscript类缓存(C:\用户\Avishek.gradle\缓存\2.2.1\脚本\asLocalRepo14_dkwbdtenxxgt2q2wfe57wj30b\InitScript\initscript)。java.io.FileNotFound

  • 我是Android Studio的新手,我一直得到这个错误。我已经研究和尝试了删除。梯度,关闭程序和重启,检查省电模式,清理和重新运行。任何其他想法都将不胜感激。昨晚它工作得很好,现在我得到了这个错误。 java.io.FileNotFoundException:C:\users\owner.gradle\caches\2.10\scripts\aslocalRepo6_4RDYKQO5VJPJF