无法使用Kerberos Keytab和kinit缓存进行身份验证

时间:2019-07-01 19:29:41

标签: ldap kerberos keytab

我正在使用密钥表,并在Windows命令行上使用kinit命令对其进行设置。我收到消息“新票证已存储在缓存文件中”。此后,当我运行Java应用程序访问密钥的密钥表文件时,出现以下错误。

Authentication attempt failed javax.security.auth.login.LoginException: No key to store
javax.security.auth.login.LoginException: No key to store
    at com.sun.security.auth.module.Krb5LoginModule.commit(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)

我正在尝试使用ldap连接到活动目录。以下是配置设置:

-Djavax.security.auth.useSubjectCredsOnly=false
-Djava.security.auth.login.config=C:\Users\cXXXXXX\Git\gssapi_jaas.conf
-Dsun.security.krb5.debug=true

Debug是true storeKey是useTicketCache是​​true useKeyTab是doNotPrompt是true ticketCache是​​null isInitiator是KeyTab是

C:\ Users \ cXXXXXX \ Git \ abcd.keytab refreshKrb5Config为false主体为xxxx_dev@xxxx.xxxxxx.COM tryFirstPass为false useFirstPass为false storePass为false clearPass为false     从缓存中获取TGT

  
    
      

KinitOptions缓存名称为C:\ Users \ cXXXXXX \ krb5cc_cXXXXXX       调试客户端主体为xxxx_dev@xxxx.xxxxxx.COM       调试服务器主体为krbtgt/xxxx.xxxxxx.COM@Txxxx.xxxxxx.COM       调试键类型:23       调试时间:2019年7月1日星期一14:20:21       调试开始时间:2019年7月1日星期一14:20:21       调试结束时间:2019年7月2日星期二00:20:21       调试renew_till时间:空       CCacheInputStream:readFlags()初始; PRE_AUTH;           主机地址为/xx.xx.xxx.xx           主机地址为/ xxx:0:0:0:xxxx:xxxx:xxxx:xxxx       KrbCreds在凭证缓存中找到默认的票证授予票证。           Java配置名称:null           本机配置名称:C:\ windows \ krb5.ini       从LSA获得了TGT:凭据:                 客户端=sxxxx_dev@xxxx.xxxxxx.COM                 服务器=krbtgt/Txxxx.xxxxxx.COM@Txxxx.xxxxxx.COM               authTime = 20190701182021Z              startTime = 20190701182021Z                endTime = 20190702042021Z              renewTill = null                  flags = INITIAL; PRE-AUTHENT           EType(关键字)= 23              (tkt键)= 18           主体是sxxxx_dev@xxxx.xxxxxx.COM

    
  

在添加kinit缓存文件之前,我能够至少验证该帐户,然后我遇到了GSSapi安全性问题。试图解决我添加了缓存的问题,这个新问题开始发生

public static void main(String[] args) {

    // 1. Log in (to Kerberos)
    LoginContext lc = null;
    try {
        /*lc = new LoginContext(Azrm017.class.getName(),
        new LuwCallBackHandler());
*/
        lc = new LoginContext("Azrm017");
        // Attempt authentication
        // You might want to do this in a "for" loop to give
        // user more than one chance to enter correct username/password
        lc.login();

    } catch (LoginException le) {
        System.err.println("Authentication attempt failed " + le);
        le.printStackTrace();
        System.err.println("Authentication attempt failed " + le.getSuppressed());

        System.exit(-1);
    }

    // 2. Perform JNDI work as logged in subject
    NamingEnumeration<SearchResult> ne =
            (NamingEnumeration<SearchResult>) Subject.doAs(lc.getSubject(),
                new SearchAction());
    while(ne.hasMoreElements()) {
        System.out.println(">>>> : " + ne.nextElement().getName());
    }

    //Subject.doAs(lc.getSubject(), new JndiAction(args));
    }
}


/**
 * The application must supply a PrivilegedAction that is to be run
 * inside a Subject.doAs() or Subject.doAsPrivileged().
 */
class SearchAction implements java.security.PrivilegedAction {

    public Object run() {

        // Set up the environment for creating the initial context
        Hashtable<String, String> env = new Hashtable<> (11);
        env.put(Context.INITIAL_CONTEXT_FACTORY,
            "com.sun.jndi.ldap.LdapCtxFactory");
        String cn = "dn:CN=xxxxxxx,OU=Service xxxxx,OU=Accounts,OU=xxxxx,DC=test,DC=xxxxxx,DC=com";
        env.put(Context.PROVIDER_URL, "ldap://test.xxxxxxx.com:389");
        env.put(Context.SECURITY_AUTHENTICATION, "GSSAPI");
        env.put("javax.security.sasl.server.authentication", "true");
        env.put("javax.security.sasl.qop", "auth-conf");

        DirContext ctx = null;
        try {
           // Create initial context
           ctx = new InitialDirContext(env);

           SearchControls ctls = new SearchControls();
           ctls.setReturningAttributes(
                 new String[] {"displayName", "mail","description", "suSunetID"});

           NamingEnumeration<SearchResult> answer =
                ctx.search("cn=People, dc=test, dc=xxxxxxxx, dc=com",
                                 "(&(cn=p*)(sn=s*))", ctls);

            return answer;


        } catch (Exception e) {
               e.printStackTrace();
        }
         // Close the context when we're done
        finally {
            closeContext(ctx);
        }
        return null;
    }

位于上方

1 个答案:

答案 0 :(得分:0)

这是Krb5LoginModule选项的错误组合。如果希望启动程序存储密钥,则必须使用该密钥来获取票证(即useTicketCache不应为true)。

为什么要存储密钥?发起人还会充当接受者吗?如果是,则应该使用密钥标签进行身份验证(即useTicketCache = false),或者使用ENC-TKT-IN-SKEY方式(即storeKey = false)进行验证。