在Karaf中以编程方式设置JAAS配置(Kerberos)文件

时间:2018-02-15 14:39:28

标签: java kerberos apache-karaf jaas

在Karaf(7)中使用Kerberos身份验证连接到Ldap服务器时出现问题。我无法使用System.setProperty(" java.security.auth.login.config"," /path/jaas.conf")通过jaas.conf文件加载kerberos内容。 。因此,我尝试了一种程序化的方法。问题是它破坏了想要使用Krb5LoginModule的其他模块/应用程序的配置,即当我设置配置时,先前的配置被销毁。有没有办法避免这种情况?

一些代码

package com.company.one;

import com.sun.security.auth.module.Krb5LoginModule;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.directory.Attributes;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import javax.security.auth.login.AppConfigurationEntry;
import javax.security.auth.login.Configuration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

public class TestLdap {

    public void testLdap() {
        Configuration jaasConfig = createJaasConfig();
        Configuration.setConfiguration(jaasConfig);
        Properties props = new Properties();
        props.setProperty(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        props.setProperty(Context.PROVIDER_URL, "ldap://myldap:389");
        props.setProperty(Context.URL_PKG_PREFIXES, "com.sun.jndi.url");
        props.setProperty(Context.SECURITY_AUTHENTICATION, "GSSAPI");
        final String filter = "(&(objectClass=employee)(uid=someId))";
        LdapContext ctx = null;

        try {
            ctx = new InitialLdapContext(props, null);
            ctx.setRequestControls(null);
            NamingEnumeration<?> namingEnum = ctx.search("dc=company,dc=se", filter, getSimpleSearchControls());
            while (namingEnum.hasMore()) {
                SearchResult result = (SearchResult) namingEnum.next();
                Attributes attrs = result.getAttributes();
                if (attrs.get("uid") != null) {
                    log.info("Attrs = {}", attrs);
                }
            }
            namingEnum.close();
        } catch (Exception e) {
            e.printStackTrace();
            log.info(e.getMessage());
        }
    }

    private static Configuration createJaasConfig() {

        // Create entry options.
        Map<String, Object> options = new HashMap<String, Object>();
        options.put("debug", "true");
        options.put("doNotPrompt", "true");
        options.put("storeKey", "true");
        options.put("principal", "nameofprincipal");
        options.put("useKeyTab", "true");
        options.put("keyTab", "/local/foo/conf/mykeytab");

        // Create entries.
        AppConfigurationEntry[] entries = {
                new AppConfigurationEntry(
                        Krb5LoginModule.class.getCanonicalName(),
                        AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
                        options)
        };

        // Create configuration.
        return new Configuration() {
            @Override
            public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
                return entries;
            }
        };

    }
}

1 个答案:

答案 0 :(得分:0)

您可以在蓝图中制作jaas-config并进行部署:

 <?xml version="1.0" encoding="UTF-8"?>
 <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:jaas="http://karaf.apache.org/xmlns/jaas/v1.1.0"
           xsi:schemaLocation="
                http://www.osgi.org/xmlns/blueprint/v1.0.0
                http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">

    <jaas:config name="XX.COM" rank="1">
        <jaas:module name="myname" className="com.sun.security.auth.module.Krb5LoginModule" flags="required">
            initialContextFactory=com.sun.jndi.ldap.LdapCtxFactory
            principal=myprincipal@xx.com
            useKeyTab=true
            keyTab=/etc/krb5.keytab-test
            storeKey=true
            doNotPrompt=true
            debug=true
            refreshKrb5Config=true
        </jaas:module>
    </jaas:config>
</blueprint>

然后你可以制作类似的代码:

private void getPerson(Person person, String filter) throws NamingException {
    final Hashtable gssapiEnv = createEnv();

    final CallbackHandler callbackHandler = callbacks -> {
      for (Callback callback : callbacks) {
        if (callback instanceof RealmCallback) {
          ((RealmCallback) callback).setText("XX.COM");
        }
      }
    };

    final LoginContext lc;
    try {
      lc = new LoginContext("XX.COM", callbackHandler);
      lc.login();

      final LdapContext ctx = Subject.doAs(lc.getSubject(), (PrivilegedAction<LdapContext>) () -> {
        InitialLdapContext result = null;
        try {
          result = new InitialLdapContext(gssapiEnv, null);
        } catch (NamingException ex) {
          ex.printStackTrace();
        }
        return result;
      });

      final NamingEnumeration<?> namingEnum = ctx.search("dc=xx,dc=com", filter, getSimpleSearchControls());
      while (namingEnum.hasMore()) {
        readPerson(ctx, person, namingEnum);
      }
      namingEnum.close();
    } catch (LoginException e) {
      e.printStackTrace();
    }

  }

private Hashtable createEnv() {
    final Hashtable<String, String> env = new Hashtable<>(11);
      System.setProperty("java.security.krb5.kdc", "kerberos.xx.com");
      System.setProperty("java.security.krb5.realm","XX.COM");

      env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
      env.put(Context.PROVIDER_URL, "ldap://myldap.xx.com:389");
      env.put(Context.SECURITY_AUTHENTICATION, "GSSAPI");
      env.put(Context.SECURITY_PRINCIPAL, "XX.COM");

    return env;
  }