使用 GSSAPI

问题描述

请注意:- 我只想验证是否可以使用 JAAS/GSSAPI 实现以下目标。我找不到任何指针。

让我首先清除对我的应用程序的限制:

  1. 我们不能有静态的 krb.conf 文件。它是动态的,不断变化的。因此,无法在内存中缓存 LoginContext 对象,因为一旦 krb.conf 文件修改主题的凭据就会失效。
  2. 我们想要管理大量我们没有任何先验信息的领域,因此无法使用静态 krb.conf 文件
  3. sun.security.krb5.internal.tools.Kinit”是专有的,总是收到警告,它可能会在未来的版本中被删除。所以我们不能使用它来生成缓存,因为存在运行时问题的风险。注意:即使 krb.conf 文件本机更改,缓存的 TGT 也不会过期。但这里的问题是,我们必须使生成和维护 krb.conf 文件代码变得非常复杂。我们想避免这种情况
  4. 我们保留使用 Runtime#exec(...) 运行 kinit 工具的选项作为生成 TGT 缓存文件的最后手段(这将减少对 sun.security.krb5.internal.tools.Kinit 的依赖包),但会使我们的 krb.conf 生成和维护逻辑更加复杂。
  5. 我正在寻找更简单的解决方案。
  6. 我们当前的实现非常简单:我们更改 krb.conf 文件以适应当前领域和域信息,然后删除文件。一切都非常动态,效率很高,但问题是,我们无法缓存 TGT 和服务票证,这会增加 KDC 服务器的负载并导致性能下降!

通过全面的介绍,让我们转向我正在尝试的 PoC。请提供指点或:

  1. 我是否朝着正确的方向前进?
  2. 我所设想的事情是否可能实现?
  3. 如果你们中有人遇到过这种情况,你们采用了什么策略?
We are connecting to Active Directory DCs to form a LdapContext/ DirContext to fetch the AD object Data.

当没有可用的缓存数据时,照常继续创建 LoginContext:

    System.setProperty("java.security.krb5.conf","C:\\Windows\\krb5.ini");
    System.setProperty("sun.security.jgss.debug","true");
    LoginContext lc = null;
    try {
        lc = new LoginContext(LdapCtxGSSAPIEx.class.getName(),new LoginCallbackHandler(username,password));

        // 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);
        System.exit(-1);
    }

解决方案 #1:

创建有效的 LoginContext 后,使用 GSSAPI 获取 ldap 的服务票证。我知道在 PrivilegedAction#run() 中形成 LdapContext 的另一种方式(实际上是我们当前的实现,并在解决方案#2 中显示)。但这对缓存没有帮助。因此,尝试使用 PoC 来存储服务票证而不是 TGT。 获取ldap服务票如下

    // servicePrincipalName = ldap/ad01.example.lab@EXAMPLE.LAB
    GSSManager manager = GSSManager.getInstance();
    GSSName serverName = manager.createName( servicePrincipalName,GSSName.NT_HOSTBASED_SERVICE);
    final GSSContext context = manager.createContext( serverName,krb5OID,null,GSSContext.DEFAULT_LIFETIME);
    // The GSS context initiation has to be performed as a privileged action.
    byte[] serviceTicket = Subject.doAs( subject,new PrivilegedAction<byte[]>() {
        public byte[] run() {
            try {
                byte[] token = new byte[0];
                // This is a one pass context initialisation.
                context.requestMutualAuth( false);
                context.requestCredDeleg( false);
                return context.initSecContext( token,token.length);
            }
            catch ( GSSException e) {
                e.printstacktrace();
                return null;
            }
        }
    });

问题:

  1. 我如何使用此服务票据来形成 LdapContext
  2. 我可以将此票证存储在文件中(编码),然后以相同的方式使用票证来形成 LdapContext 吗?

解决方案 #2: 在大多数教程和我们当前的实现中都可以看到创建 LdapContext:

 DirContext ctx = Subject.doAs(lc.getSubject(),new JndiAction<DirContext>(args,providerURL ));


 class JndiAction<DirContext> implements java.security.PrivilegedAction<DirContext> {
 .......
      public DirContext run() {
          return performJndioperation(args,this.providerURL);
      }

      public DirContext performJndioperation(String[] args,String providerURL){
         ......
         env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");

         // Must use fully qualified hostname
         env.put(Context.PROVIDER_URL,providerURL);

         // Request the use of the "GSSAPI" SASL mechanism
         // Authenticate by using already established Kerberos credentials
         env.put(Context.Security_AUTHENTICATION,"GSSAPI");

         // Request mutual authentication
         env.put("javax.security.sasl.server.authentication","true"); 

         DirContext ctx = new InitialDirContext(env);

         return ctx;
         ......

      }
 .......

 }

当上面代码中的这一行:DirContext ctx = new InitialDirContext(env); 被执行时:Subject 被填充了一个新的 PrivateCredential,其服务主体为:ldap/ad01.example.lab@EXAMPLE.LAB

问题:我可以存储此服务票证以供进一步参考以创建 LdapContext 而不是一遍又一遍地执行所有身份验证步骤吗?

什么是委托凭证?他们会帮助解决我的问题吗?


更新: 为什么在缓存中存储服务票而不是 TGT? ---> 明确避免 kinit。存储服务票据将很容易适应我们当前的解决方案。此外,这将是一个临时解决方案,因为我们将根据客户的需要询问 krb.conf 文件,并免除创建 krb.conf 文件的责任。但现在,我们必须这样做!

请帮忙!

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)