Kerberos和LDAP:为什么Java 6在使用Kerberos时截断LDAP主机名?

Kerberos和LDAP:为什么Java 6在使用Kerberos时截断LDAP主机名?,java,ldap,kerberos,gssapi,jgss,Java,Ldap,Kerberos,Gssapi,Jgss,我的任务是通过JavaGSSAPI连接到KerberizedLDAP服务器。我有一个小示例应用程序,用于测试我的连接、Kerberos配置、连接参数等,以确保我可以连接到LDAP服务器并检索数据。其代码如下所示: import java.io.FileInputStream; import java.io.IOException; import java.security.PrivilegedActionException; import java.security.PrivilegedExce

我的任务是通过JavaGSSAPI连接到KerberizedLDAP服务器。我有一个小示例应用程序,用于测试我的连接、Kerberos配置、连接参数等,以确保我可以连接到LDAP服务器并检索数据。其代码如下所示:

import java.io.FileInputStream;
import java.io.IOException;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Properties;

import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.Control;
import javax.naming.ldap.InitialLdapContext;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;

public class TestKerberizedLdap implements Runnable {

    public static void main(String[] args) {
        Runnable rn = null;
        if (args.length == 1) {
            rn = new TestKerberizedLdap(args[0]);
        }
        else if (args.length == 0) {
            rn = new TestKerberizedLdap("C:/dev/projects/TestKerberizedLdap/src/testkerberizedldap.properties");
        }
        else {
            printUsage();
            return;
        }

        rn.run();
    }

    private static final String loginModuleClassName = "com.sun.security.auth.module.Krb5LoginModule";
    private static final String koid = "1.2.840.113554.1.2.2";
    private static final String soid = "1.3.6.1.5.5.2";

    private Subject subject;
    private DirContext ldapContext;
    private String username;
    private String password;
    private String ldapHost;

    private TestKerberizedLdap(String propFileName) {
        Properties prop = new Properties();
        try {
            FileInputStream iStream = new FileInputStream(propFileName);
            prop.load(iStream);
            iStream.close();
        }
        catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println("Properties found:");
        for (String propName : prop.stringPropertyNames()) {
            System.out.println(propName + " = " + prop.getProperty(propName));
        }
        System.out.println();

        System.setProperty("java.security.krb5.conf", prop.getProperty("krbConf"));
        System.setProperty("java.security.krb5.debug", "true");
        System.setProperty("sun.security.krb5.debug", "true");

        ldapHost = prop.getProperty("ldapHost");
        username = prop.getProperty("user");
        password = prop.getProperty("password");
        subject = null;
        ldapContext = null;
    }

    public void run() {
        try {
            initSubject();
            if (subject != null) {
                initContextKerberized();
            }
        }
        catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private void initContextKerberized() throws Exception {
        Subject.doAs(subject, new PrivilegedExceptionAction<Object>() {
            public Object run() throws Exception {
                Hashtable<String, String> env = new Hashtable<String, String>();
                env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
                env.put(Context.PROVIDER_URL, ldapHost);
                env.put(Context.SECURITY_AUTHENTICATION, "GSSAPI");
                ldapContext = new InitialLdapContext(env, new Control[0]);

                // Do stuff with ldapContext here...
                searchLdapDirectory();

                return null;
            }
        });
    }

    private void searchLdapDirectory() throws NamingException {
        String base = "CN=Users";
        String filter = "(objectclass=user)";
        SearchControls sc = new SearchControls();
        sc.setSearchScope(SearchControls.SUBTREE_SCOPE);
        NamingEnumeration<SearchResult> ne = ldapContext.search(base, filter, sc);
        int numElements = 0;
        System.out.println();
        while (ne.hasMoreElements()) {
            SearchResult sr = ne.nextElement();
            Attributes attr = sr.getAttributes();
            System.out.println(attr.get("name").get());
            numElements++;
        }
        System.out.println("The number of elements returned was " + numElements);
    }

    private void initSubject() throws InstantiationException, ClassNotFoundException, IllegalAccessException {
        LoginModule module = null;
        try {
            module = (LoginModule) Class.forName(loginModuleClassName).newInstance();
            subject = new Subject();
            Map<String, String> options = new HashMap<String, String>();
            Map<String, Object> sharedState = new HashMap<String, Object>();

            if ((username != null) && (password != null)) {
                sharedState.put("javax.security.auth.login.password", password.toCharArray());
                sharedState.put("javax.security.auth.login.name", username);
                options.put("principal", username);
                options.put("storeKey", "true");
                options.put("useFirstPass", "true");
            }
            else {
                options.put("principal", username);
                options.put("useTicketCache", "true");
                options.put("doNotPrompt", "true");
                options.put("renewTGT", "true");
            }
            options.put("debug", "true");
            options.put("refreshKrb5Config", "true");

            module.initialize(subject, null, sharedState, options);
            module.login();
            module.commit();
        }
        catch (LoginException ex) {
            ex.printStackTrace();
            subject = null;
            if (module != null) {
                try {
                    module.abort();
                }
                catch (LoginException ex2) {
                    ex2.printStackTrace();
                }
            }
        }
    }

    private static void printUsage() {
        System.out.println();
        System.out.println("Usage: TestKerberizedLdap <property file name>");
        System.out.println();
    }
}
import java.io.FileInputStream;
导入java.io.IOException;
导入java.security.PrivilegedActionException;
导入java.security.PrivilegedExceptionAction;
导入java.util.HashMap;
导入java.util.Hashtable;
导入java.util.Map;
导入java.util.Properties;
导入javax.naming.Context;
导入javax.naming.NamingEnumeration;
导入javax.naming.NamingException;
导入javax.naming.directory.Attributes;
导入javax.naming.directory.DirContext;
导入javax.naming.directory.SearchControls;
导入javax.naming.directory.SearchResult;
导入javax.naming.ldap.Control;
导入javax.naming.ldap.InitialLdapContext;
导入javax.security.auth.Subject;
导入javax.security.auth.login.LoginContext;
导入javax.security.auth.login.LoginException;
导入javax.security.auth.spi.LoginModule;
公共类TestKerberizedLdap实现可运行{
公共静态void main(字符串[]args){
Runnable rn=null;
如果(args.length==1){
rn=新的TestKerberizedLdap(args[0]);
}
else if(args.length==0){
rn=newtestkerberizedldap(“C:/dev/projects/TestKerberizedLdap/src/TestKerberizedLdap.properties”);
}
否则{
打印用法();
返回;
}
rn.run();
}
私有静态最终字符串loginModuleClassName=“com.sun.security.auth.module.Krb5LoginModule”;
专用静态最终字符串koid=“1.2.840.113554.1.2.2”;
专用静态最终字符串soid=“1.3.6.1.5.5.2”;
私人主体;
私有目录上下文ldapContext;
私有字符串用户名;
私有字符串密码;
私有字符串ldapHost;
私有TestKerberizedLdap(字符串propFileName){
Properties prop=新属性();
试一试{
FileInputStream iStream=新的FileInputStream(propFileName);
道具载荷(iStream);
iStream.close();
}
捕获(IOE异常){
e、 printStackTrace();
}
System.out.println(“找到的属性:”);
对于(字符串propName:prop.stringPropertyNames()){
System.out.println(propName+“=”+prop.getProperty(propName));
}
System.out.println();
setProperty(“java.security.krb5.conf”,prop.getProperty(“krbConf”);
setProperty(“java.security.krb5.debug”,“true”);
set属性(“sun.security.krb5.debug”、“true”);
ldapHost=prop.getProperty(“ldapHost”);
用户名=prop.getProperty(“用户”);
password=prop.getProperty(“密码”);
subject=null;
ldapContext=null;
}
公开募捐{
试一试{
initSubject();
if(主题!=null){
initContextKerberized();
}
}
捕获(例外情况除外){
例如printStackTrace();
}
}
私有void initContextKerberized()引发异常{
Subject.doAs(Subject,newprivilegedexceptionaction(){
公共对象run()引发异常{
Hashtable env=新的Hashtable();
put(Context.INITIAL\u Context\u工厂,“com.sun.jndi.ldap.LdapCtxFactory”);
env.put(Context.PROVIDER\u URL,ldapHost);
环境put(Context.SECURITY_认证,“GSSAPI”);
ldapContext=new InitialLdapContext(env,新控件[0]);
//在这里使用ldapContext做一些事情。。。
searchLdapDirectory();
返回null;
}
});
}
私有void searchLdapDirectory()引发NamingException{
String base=“CN=Users”;
字符串筛选器=“(objectclass=user)”;
SearchControls sc=新的SearchControls();
sc.setSearchScope(SearchControls.SUBTREE_范围);
NamingEnumeration ne=ldapContext.search(基本、过滤器、sc);
整数=0;
System.out.println();
而(ne.hasMoreElements()){
SearchResult sr=ne.nextElement();
Attributes attr=sr.getAttributes();
System.out.println(attr.get(“name”).get();
numElements++;
}
System.out.println(“返回的元素数为”+numElements);
}
private void initSubject()引发实例化异常、ClassNotFoundException、IllegalAccessException{
LoginModule模块=null;
试一试{
module=(LoginModule)Class.forName(loginModuleClassName).newInstance();
主题=新主题();
Map options=newhashmap();
Map sharedState=new HashMap();
如果((用户名!=null)和&(密码!=null)){
sharedState.put(“javax.security.auth.login.password”,password.tocharray());
sharedState.put(“javax.security.auth.login.name”,用户名);
期权。看跌期权(“委托人”,用户名);
期权。看跌期权(“storeKey”、“true”);
期权。看跌期权(“useFirstPass”、“true”);
}
否则{
期权。看跌期权(“委托人”,用户名);
期权。看跌期权(“useTicketCache”、“true”);
期权。看跌期权(“不提示”、“真实”);
期权。看跌期权(“续期”、“真实”);
}
选项。放置(“调试”、“真”);
看跌期权(“refreshKrb5Config”、“true”);
初始化(subject、null、sharedState、options);
module.login();
commit()模块;
}
捕获(LoginException ex){
例如printStackTrace();
subject=null;
如果(模块!=null){
    Found ticket for user1@2K8.HLP.NET to go to krbtgt/2K8.HLP.NET@2K8.HLP.NET expiring on Thu Jun 04 00:47:07 PDT 2015
Entered Krb5Context.initSecContext with state=STATE_NEW
Found ticket for user1@2K8.HLP.NET to go to krbtgt/2K8.HLP.NET@2K8.HLP.NET expiring on Thu Jun 04 00:47:07 PDT 2015
Service ticket not found in the subject
>>> Credentials acquireServiceCreds: same realm
default etypes for default_tgs_enctypes: 23 16 3 1.
>>> CksumType: sun.security.krb5.internal.crypto.RsaMd5CksumType
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
>>> KrbKdcReq send: kdc=172.23.5.151 UDP:88, timeout=30000, number of retries =3, #bytes=1289
>>> KDCCommunication: kdc=172.23.5.151 UDP:88, timeout=30000,Attempt =1, #bytes=1289
>>> KrbKdcReq send: #bytes read=92
>>> KrbKdcReq send: #bytes read=92
>>> KdcAccessibility: remove 172.23.5.151:88
>>> KDCRep: init() encoding tag is 126 req type is 13
>>>KRBError:
     sTime is Wed Jun 03 14:47:07 PDT 2015 1433368027000
     suSec is 109093
     error code is 7
     error Message is Server not found in Kerberos database
     realm is 2K8.HLP.NET
     sname is ldap/2k8.hlp.net
     msgType is 30
java.security.PrivilegedActionException: javax.naming.AuthenticationException: GSSAPI [Root exception is javax.security.sasl.SaslException: GSS initiate failed [Caused by GSSException: No valid credentials provided (Mechanism level: Server not found in Kerberos database (7))]]
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.security.auth.Subject.doAs(Subject.java:396)
    at TestKerberizedLdap.initContextKerberized(TestKerberizedLdap.java:95)
    at TestKerberizedLdap.run(TestKerberizedLdap.java:85)
    at TestKerberizedLdap.main(TestKerberizedLdap.java:39)
Caused by: javax.naming.AuthenticationException: GSSAPI [Root exception is javax.security.sasl.SaslException: GSS initiate failed [Caused by GSSException: No valid credentials provided (Mechanism level: Server not found in Kerberos database (7))]]
    at com.sun.jndi.ldap.sasl.LdapSasl.saslBind(LdapSasl.java:150)
    at com.sun.jndi.ldap.LdapClient.authenticate(LdapClient.java:214)
    at com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2694)
    at com.sun.jndi.ldap.LdapCtx.<init>(LdapCtx.java:293)
    at com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(LdapCtxFactory.java:175)
    at com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(LdapCtxFactory.java:193)
    at com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(LdapCtxFactory.java:136)
    at com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(LdapCtxFactory.java:66)
    at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:667)
    at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:288)
    at javax.naming.InitialContext.init(InitialContext.java:223)
    at javax.naming.ldap.InitialLdapContext.<init>(InitialLdapContext.java:134)
    at TestKerberizedLdap$1.run(TestKerberizedLdap.java:101)
    ... 5 more
Caused by: javax.security.sasl.SaslException: GSS initiate failed [Caused by GSSException: No valid credentials provided (Mechanism level: Server not found in Kerberos database (7))]
    at com.sun.security.sasl.gsskerb.GssKrb5Client.evaluateChallenge(GssKrb5Client.java:194)
    at com.sun.jndi.ldap.sasl.LdapSasl.saslBind(LdapSasl.java:105)
    ... 17 more
Caused by: GSSException: No valid credentials provided (Mechanism level: Server not found in Kerberos database (7))
    at sun.security.jgss.krb5.Krb5Context.initSecContext(Krb5Context.java:663)
    at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImpl.java:230)
    at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImpl.java:162)
    at com.sun.security.sasl.gsskerb.GssKrb5Client.evaluateChallenge(GssKrb5Client.java:175)
    ... 18 more
Caused by: KrbException: Server not found in Kerberos database (7)
    at sun.security.krb5.KrbTgsRep.<init>(KrbTgsRep.java:61)
    at sun.security.krb5.KrbTgsReq.getReply(KrbTgsReq.java:185)
    at sun.security.krb5.internal.CredentialsUtil.serviceCreds(CredentialsUtil.java:294)
    at sun.security.krb5.internal.CredentialsUtil.acquireServiceCreds(CredentialsUtil.java:106)
    at sun.security.krb5.Credentials.acquireServiceCreds(Credentials.java:557)
    at sun.security.jgss.krb5.Krb5Context.initSecContext(Krb5Context.java:594)
    ... 21 more
Caused by: KrbException: Identifier doesn't match expected value (906)
    at sun.security.krb5.internal.KDCRep.init(KDCRep.java:133)
    at sun.security.krb5.internal.TGSRep.init(TGSRep.java:58)
    at sun.security.krb5.internal.TGSRep.<init>(TGSRep.java:53)
    at sun.security.krb5.KrbTgsRep.<init>(KrbTgsRep.java:46)
    ... 26 more