如何让ldap证书绕过使用Java的相互认证

时间:2013-08-19 21:24:13

标签: java ldap certificate jndi starttls

我正在编写一个可以从远程服务器获取Ldap证书的项目。当服务器不需要相互认证时,它适用于通用模式。但是,当我尝试需要相互认证的服务器时,它会失败。这是代码:

    String serverSpec = null;
    boolean enableAnonSuites = false;
    boolean isTracing = false;

    // Try and parse command line arguments.
    try {

        serverSpec = "ldap://10.47.16.60:389";
    }

    catch (Exception e) {
        trace(true,e.toString());
        usage();
        return;
    }

    try {

        // Create a SocketFactory that will be given to LDAP for 
        // building SSL sockets
        MySocketFactory msf = new MySocketFactory(isTracing,
                enableAnonSuites);

        // Set up environment for creating initial context
        Hashtable env = new Hashtable(11);
        env.put(Context.INITIAL_CONTEXT_FACTORY, 
                "com.sun.jndi.ldap.LdapCtxFactory");


        // Must use the name of the server that is found in its certificate
        env.put(Context.PROVIDER_URL, 
                serverSpec
                );

        // Create initial context
        trace(isTracing,"Creating new Ldapcontext");
        LdapContext ctx = new InitialLdapContext(env, null);

        // Start 
        trace(isTracing,"Performing StartTlsRequest");
        StartTlsResponse tls = null;

        try {
            tls = (StartTlsResponse)ctx.extendedOperation(new StartTlsRequest());
        }
        catch (NamingException e) {
            trace(true,"Unable to establish SSL connection:\n"
                    +e);
            return;
        }


        // The default JSSE implementation will compare the hostname of
        // the server with the hostname in the server's certificate, and
        // will not proceed unless they match.  To override this behaviour,
        // you have to provide your own HostNameVerifier object.  The 
        // example below simply bypasses the check

        tls.setHostnameVerifier(new HostnameVerifier() {
            public boolean verify(String hostname, SSLSession session) 
            {
                return true;
            }
        });
        // Negotiate SSL on the connection using our own SocketFactory
        trace(isTracing,"Negotiating SSL");
        SSLSession sess = null;
        sess = tls.negotiate(msf);

        X509Certificate[] cert = sess.getPeerCertificateChain();

异常信息如下:“javax.net.ssl.SSLException:收到致命警报:内部错误”,它发生在“negotiate”方法中。我分析了wireshark跟踪信息,我确信这是因为服务器需要相互认证。现在,我想知道com.sun.jndi.ldap包中是否存在某些可能对此问题有用的类。有人可以帮忙吗?

1 个答案:

答案 0 :(得分:3)

你做不到。如果在JDK中有这样的类,那将是不安全的。如果服务器需要客户端证书而没有客户端证书,则必须提供一个。这就是例外。