首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JAAS -无法将Kerberos票证持久化到缓存文件,并且无法从头创建缓存。和其他细节

JAAS -无法将Kerberos票证持久化到缓存文件,并且无法从头创建缓存。和其他细节
EN

Stack Overflow用户
提问于 2017-08-02 14:27:30
回答 4查看 7.7K关注 0票数 5

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

我的应用程序能够执行'i‘,但是不能执行'ii',它正确地对用户进行身份验证(创建主题/主体),但是它不会将Krb票证持久化到缓存中。

问题

  1. 我如何实现/实现这一点?
  2. 然后..。这将在空/不存在时创建Kerberos缓存文件吗?-如何通过Java编程实现缓存文件的创建/初始化?
  3. 然后..。出于好奇,是否能够管理JaaS密钥环?(目前Jaas无法自动管理它们)
  4. Java JaaS只能管理/持久化缓存中默认主体的票证吗?-或者如何使用JaaS管理在单个缓存文件中的许多主体的票证?

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

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

我正在FreeIPA客户机和服务器配置的Linux领域中测试客户端应用程序。我有一个为领域AUTHDEMO.IT提供KDC的Linux,以及一个被AUTHDEMO.IT领域认可的linux。krb5.conf配置:

代码语言:javascript
复制
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

代码语言:javascript
复制
JaasDemo {
   com.sun.security.auth.module.Krb5LoginModule required 
   useTicketCache=true
   principal=uclient
   debug=true; 
};

我没有指定默认的缓存文件名,我已经在调试中验证它默认为:/tmp/krb5cc_1000,其中1000是正在运行的用户的uid。

在JaasDemo类实例中,我使用此login方法执行身份验证:

代码语言:javascript
复制
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日志记录的选项):

代码语言:javascript
复制
java  -Dsun.security.krb5.debug=true -Dsun.security.jgss.debug=true -Djava.security.auth.login.config=jaas.conf -jar myapp.jar

下面是应用程序在不同情况下的输出,请注意,当询问时,用户交互地提供正确的凭据。第一例不存在的/tmp/krb5cc_1000文件:

代码语言:javascript
复制
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状态优先于应用程序执行:

代码语言:javascript
复制
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

申请产出:

代码语言:javascript
复制
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”的票证添加到缓存文件中。

问候

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2017-08-10 15:52:28

终于找到了问题1+ 2的答案

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

Kinit代码对于理解内部私有Kerberos代码的内部工作和定制它非常有用。例如,有一个KDCOptions实例,您可以手动配置它,以便请求可更新的票证等等。让我们来研究它吧!

请考虑:

  • 在今后的JDK版本中,并不能保证内部代码的接口保持不变。
  • 不能保证内部代码的接口在不同的JDK供应商之间是相同的。

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

,大图,

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

下一步

目前,我正试图将Kerberos票证直接从Subject对象中的凭据中保存到ccache。

我将尝试使用sun.security.krb5.internal.ccache.FileCredentialCache类,但它看起来是一种低级别的方法。让我们看一下kinit代码中CredentialCache抽象类的使用,可能会很有用。如果成功,我将更新线程。

谢谢

感谢Michael向我展示了sun.security.krb5.internal包,在那里我终于找到了kinit代码。

问候

票数 6
EN

Stack Overflow用户

发布于 2017-08-02 23:33:38

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

票数 4
EN

Stack Overflow用户

发布于 2017-08-10 15:58:45

其他问题.

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

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

4 - Java JaaS只能管理/持久化缓存中默认主体的票证吗?或者如何使用JaaS管理在单个缓存文件中有许多主体的票证的情况?

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45463635

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档