Java LDAP 客户端连接 OpenLDAP 服务器(startTls)失败:(LDAP:错误代码 13 - 需要 TLS 机密性)

问题描述 投票:0回答:1

为 gerrit 配置 ldap(startTLS) 时出现错误。

我已经使用 startTLS 配置了 ldap 服务器,并且运行良好。

  • ldapsearch -x -W -ZZ -H ldap://test.com -D cn=admin,ou=manager,dc=test,dc=com  -b dc=test,dc=com
    ,这将返回预期的结果。
  • ldapsearch -x -W -H ldap://test.com -D cn=admin,ou=manager,dc=test,dc=com  -b dc=test,dc=com
    , 这会返回错误
    ldap_bind: Confidentiality required (13), additional info: TLS confidentiality required
    ,也可以按预期工作,无需
    -ZZ

etc/gerrit.conf
如下:

[gerrit]
        basePath = git
        canonicalWebUrl = http://localhost:8080/
        serverId = 956c31a1-1d24-4893-ad73-ca7aa0e9cbfc
[container]
        javaOptions = "-Dflogger.backend_factory=com.google.common.flogger.backend.log4j.Log4jBackendFactory#getInstance"
        javaOptions = "-Dflogger.logging_context=com.google.gerrit.server.logging.LoggingContext#getInstance"
        user = root
        javaHome = /usr/lib/jvm/java-17-openjdk-amd64
[index]
        type = lucene
[auth]
        type = LDAP
        gitBasicAuthPolicy = LDAP
[receive]
        enableSignedPush = false
[sendemail]
        smtpServer = test.com
        smtpEncryption = TLS
        smtpUser = gerrit
[sshd]
        listenAddress = *:29418
[httpd]
        listenUrl = http://*:8080/
[cache]
        directory = cache
[ldap]
        startTls = true
        server = ldap://test.com
        username = cn=admin,ou=manager,dc=test,dc=com
        accountBase = ou=People,dc=test,dc=com
        groupBase = ou=Group,dc=test,dc=com

从 gerrit web 登录时,失败并显示错误日志:

javax.naming.AuthenticationNotSupportedException: [LDAP: error code 13 - TLS confidentiality required]

我的环境:

  • uname -a
    :Debian 6.1.85-1 (2024-04-11) x86_64 GNU/Linux
  • java -version
    :openjdk版本“17.0.11”2024-04-16
  • slapd -V
    :OpenLDAP: slapd 2.5.13+dfsg-5
  • gerrit
    :gerrit-3.9.4.war

我也尝试过一个简单的java客户端,但它返回了相同的错误。

附:

  1. LdapStartTlsDemo.java
import javax.naming.Context;                                                                                                               
import javax.naming.NamingEnumeration;                                                                                                     
import javax.naming.directory.Attributes;                                                                                                  
import javax.naming.directory.DirContext;                                                                                                  
import javax.naming.directory.InitialDirContext;                                                                                           
import javax.naming.directory.SearchControls;                                                                                              
import javax.naming.directory.SearchResult;                                                                                                
import javax.naming.ldap.InitialLdapContext;                                                                                               
import javax.naming.ldap.LdapContext;                                                                                                      
import java.util.Hashtable;                                                                                                                
import java.util.Properties;                                                                                                               
                                                                                                                                           
public class LdapStartTlsDemo {                                                                                                            
                                                                                                                                           
    public static void main(String[] args) {                                                                                               
        try {                                                                                                                              
            // 设置LDAP连接参数                                                                                                                  
            Hashtable<String, Object> env = new Hashtable<>();                                                                             
            env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");                                                  
            env.put(Context.PROVIDER_URL, "ldap://test.com"); // LDAP server                                                            
            env.put(Context.SECURITY_AUTHENTICATION, "simple"); // type                                                                   
            env.put(Context.SECURITY_PRINCIPAL, "cn=admin,ou=manager,dc=test,dc=com"); // DN                                   
            env.put(Context.SECURITY_CREDENTIALS, "secret"); // pw                                                                    
            env.put("java.naming.security.protocol", "tls"); // TLS                                                                      
            env.put("java.naming.ldap.starttls.required", "true"); // force StartTLS                                                           
                                                                                                                                                                                                                                             
            System.setProperty("javax.net.ssl.trustStore", "/etc/ldap/tls/CA.pem");                                                        
            // System.setProperty("javax.net.ssl.trustStorePassword", "truststore_password");                                              
                                                                                                                                           
            System.setProperty("javax.net.debug", "ssl,handshake");                                                                        
                                                                                                                                           
                                                                                                                
            LdapContext ctx = new InitialLdapContext(env, null);                                                                           
            System.out.println("Connected to LDAP server using StartTLS.");                                                                
                                                                                                                                                                                                                                                           
            SearchControls searchCtls = new SearchControls();                                                                              
            searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);                                                                       
            String searchFilter = "(objectClass=person)";                                                                                  
            String[] returnedAtts = {"cn", "sn", "mail"};                                                                                  
            searchCtls.setReturningAttributes(returnedAtts);                                                                               
                                                                                                                                           
            NamingEnumeration<SearchResult> answer = ctx.search("ou=Users,dc=example,dc=com", searchFilter, searchCtls);                   
                                                                                                                                           
            while (answer.hasMoreElements()) {                                                                                             
                SearchResult sr = answer.next();                                                                                           
                Attributes attrs = sr.getAttributes();                                                                                     
                                                                                                                                           
                System.out.println("Found User: " + attrs.get("cn").get());                                                                
                System.out.println("SN: " + attrs.get("sn").get());                                                                        
                System.out.println("Email: " + attrs.get("mail").get());                                                                   
                System.out.println("-------------------");                                                                                 
            }                                                                                                                              
                                                                                                                                           
            // 关闭连接                                                                                                                        
            ctx.close();                                                                                                                   
            System.out.println("Connection closed.");                                                                                      
        } catch (Exception e) {                                                                                                            
            e.printStackTrace();                                                                                                           
        }                                                                                                                                  
    }                                                                                                                                      
}                                                                                                                                          
  1. Java 异常堆栈跟踪
javax.naming.AuthenticationNotSupportedException: [LDAP: error code 13 - TLS confidentiality required]
        at java.naming/com.sun.jndi.ldap.LdapCtx.mapErrorCode(LdapCtx.java:3251)
        at java.naming/com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:3206)
        at java.naming/com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2992)
        at java.naming/com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2906)
        at java.naming/com.sun.jndi.ldap.LdapCtx.<init>(LdapCtx.java:348)
        at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxFromUrl(LdapCtxFactory.java:229)
        at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(LdapCtxFactory.java:189)
        at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(LdapCtxFactory.java:247)
        at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(LdapCtxFactory.java:154)
        at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(LdapCtxFactory.java:84)
        at java.naming/javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:732)
        at java.naming/javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:305)
        at java.naming/javax.naming.InitialContext.init(InitialContext.java:236)
        at java.naming/javax.naming.ldap.InitialLdapContext.<init>(InitialLdapContext.java:154)
        at com.google.gerrit.auth.ldap.Helper.createContext(Helper.java:175)
        at com.google.gerrit.auth.ldap.Helper.open(Helper.java:218)
        at com.google.gerrit.auth.ldap.LdapRealm.authenticate(LdapRealm.java:242)
        at com.google.gerrit.server.account.AccountManager.authenticate(AccountManager.java:144)
        at com.google.gerrit.httpd.auth.ldap.LdapLoginServlet.doPost(LdapLoginServlet.java:126)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
        at com.google.inject.servlet.ServletDefinition.doServiceImpl(ServletDefinition.java:293)
        at com.google.inject.servlet.ServletDefinition.doService(ServletDefinition.java:283)
        at com.google.inject.servlet.ServletDefinition.service(ServletDefinition.java:184)
        at com.google.inject.servlet.ManagedServletPipeline.service(ManagedServletPipeline.java:89)
        at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:85)
        at com.google.gerrit.httpd.raw.StaticModule$PolyGerritFilter.doFilter(StaticModule.java:395)
        at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
        at com.google.gerrit.httpd.GetUserFilter.doFilter(GetUserFilter.java:92)
        at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
        at com.google.gerrit.httpd.UniversalWebLoginFilter.doFilter(UniversalWebLoginFilter.java:75)
        at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
        at com.google.gerrit.httpd.RunAsFilter.doFilter(RunAsFilter.java:120)
        at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
        at com.google.gerrit.httpd.SetThreadNameFilter.doFilter(SetThreadNameFilter.java:62)
        at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
        at com.google.gerrit.httpd.AllRequestFilter$FilterProxy$1.doFilter(AllRequestFilter.java:139)
        at com.google.gerrit.httpd.AllowRenderInFrameFilter.doFilter(AllowRenderInFrameFilter.java:56)
        at com.google.gerrit.httpd.AllRequestFilter$FilterProxy$1.doFilter(AllRequestFilter.java:135)
        at com.google.gerrit.httpd.AllRequestFilter$FilterProxy.doFilter(AllRequestFilter.java:141)
        at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
        at com.google.gerrit.httpd.RequestCleanupFilter.doFilter(RequestCleanupFilter.java:60)
        at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
        at com.google.gerrit.httpd.RequestMetricsFilter.doFilter(RequestMetricsFilter.java:92)
        at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
        at com.google.gerrit.httpd.RequestContextFilter.doFilter(RequestContextFilter.java:64)
        at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
        at com.google.inject.servlet.ManagedFilterPipeline.dispatch(ManagedFilterPipeline.java:121)
        at com.google.inject.servlet.GuiceFilter.doFilter(GuiceFilter.java:133)
        at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193)
        at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1626)
        at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:552)
        at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233)
        at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1624)
        at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233)
        at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1440)
        at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188)
        at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:505)
        at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1594)
        at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186)
        at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1355)
        at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
        at org.eclipse.jetty.server.handler.RequestLogHandler.handle(RequestLogHandler.java:54)
        at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
        at org.eclipse.jetty.server.Server.handle(Server.java:516)
        at org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:487)
        at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:732)
        at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:479)
        at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:277)
        at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311)
        at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:105)
        at org.eclipse.jetty.io.ChannelEndPoint$1.run(ChannelEndPoint.java:104)
        at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:338)
        at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:315)
        at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:173)
        at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:131)
        at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:409)
        at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:883)
        at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1034)
        at java.base/java.lang.Thread.run(Thread.java:840)
  1. 简单演示的堆栈跟踪
root@test:~/ldap# java -Djdk.tls.client.protocols=TLSv1.2,TLSv1.3 -Djavax.net.debug=all LdapStartTlsDemo
javax.naming.AuthenticationNotSupportedException: [LDAP: error code 13 - TLS confidentiality required]
        at java.naming/com.sun.jndi.ldap.LdapCtx.mapErrorCode(LdapCtx.java:3251)
        at java.naming/com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:3206)
        at java.naming/com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2992)
        at java.naming/com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2906)
        at java.naming/com.sun.jndi.ldap.LdapCtx.<init>(LdapCtx.java:348)
        at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxFromUrl(LdapCtxFactory.java:229)
        at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(LdapCtxFactory.java:189)
        at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(LdapCtxFactory.java:247)
        at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(LdapCtxFactory.java:154)
        at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(LdapCtxFactory.java:84)
        at java.naming/javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:732)
        at java.naming/javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:305)
        at java.naming/javax.naming.InitialContext.init(InitialContext.java:236)
        at java.naming/javax.naming.ldap.InitialLdapContext.<init>(InitialLdapContext.java:154)
        at LdapStartTlsDemo.main(LdapStartTlsDemo.java:34)
ldap gerrit openldap starttls
1个回答
0
投票

对于

LdapStartTlsDemo.java
,这是一个正常工作的演示。

import javax.naming.Context;                                                                                                             
import javax.naming.NamingEnumeration;                                                                                                   
import javax.naming.directory.Attributes;                                                                                                
import javax.naming.directory.DirContext;                                                                                                
import javax.naming.directory.InitialDirContext;                                                                                         
import javax.naming.directory.SearchControls;                                                                                            
import javax.naming.directory.SearchResult;                                                                                              
import javax.naming.ldap.InitialLdapContext;                                                                                             
import javax.naming.ldap.LdapContext;
import javax.naming.ldap.StartTlsRequest;
import javax.naming.ldap.StartTlsResponse;
import javax.net.ssl.SSLSession;

import java.util.Hashtable;                                                                                                              
import java.util.Properties;                                                                                                             
                                                                                                                                         
public class LdapStartTlsDemo {
    
    private static final String LDAP_SERVER_URL = "ldap://test.com";
    private static final String LDAP_BIND_USERNAME = "cn=admin,dc=test,dc=com";
    private static final String LDAP_BIND_PASSWORD = "password";
    private static final String LDAP_BASE_DN = "ou=People,dc=test,dc=com";
                                       
    public static void main(String[] args) {                                                                                             
        try {                                                                                                                                                                                                                                        
            Hashtable<String, Object> env = new Hashtable<>();                                                                           
            env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");                                                
            env.put(Context.PROVIDER_URL, LDAP_SERVER_URL);  
            //env.put(Context.SECURITY_AUTHENTICATION, "simple");
            //env.put(Context.SECURITY_PRINCIPAL, LDAP_BIND_USERNAME);  
            //env.put(Context.SECURITY_CREDENTIALS, LDAP_BIND_PASSWORD); 

            LdapContext ctx = new InitialLdapContext(env, null);
            System.out.println("Trying to connect to LDAP server using StartTLS."); 
            StartTlsResponse tls = (StartTlsResponse) ctx.extendedOperation(new StartTlsRequest());
            tls.negotiate();

            ctx.addToEnvironment(Context.SECURITY_AUTHENTICATION, "simple");
            ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, LDAP_BIND_USERNAME);
            ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, LDAP_BIND_PASSWORD);
                                                    
            System.out.println("Connected to LDAP server using StartTLS."); 
            
            // Perform LDAP search to authenticate user
            NamingEnumeration<SearchResult> results = ctx.search(LDAP_BASE_DN, "(uid=username)", getSearchControls());

            if (results.hasMore()) {
                // successfully
                SearchResult result = results.next();
                System.out.println("User authenticated successfully");

                Attributes attrs = result.getAttributes();   
                                                                                                                                           
                System.out.println("Found User: " + attrs.get("uid").get());                                                                
                System.out.println("CN: " + attrs.get("cn").get());                                                                                                                                          
                System.out.println("-------------------"); 
            } else {
                // failed
                System.out.println("Authentication failed");
            }
            

            tls.close();
                                                                                                                                         
            // 关闭连接                                                                                                                      
            ctx.close();                                                                                                                 
            System.out.println("Connection closed.");                                                                                    
        } catch (Exception e) {                                                                                                          
            e.printStackTrace();                                                                                                         
        }                                                                                                                                
    }        
    
    private static SearchControls getSearchControls() {
        SearchControls searchCtrls = new SearchControls();
        searchCtrls.setSearchScope(SearchControls.SUBTREE_SCOPE);
        searchCtrls.setReturningAttributes(new String[] {"uid", "cn"});
        return searchCtrls;
    }
}                                                                                                                                        

这适用于 OpenJDK 11 和 17。

正如您所注意到的,注释下有三行。

//env.put(Context.SECURITY_AUTHENTICATION, "simple");
//env.put(Context.SECURITY_PRINCIPAL, LDAP_BIND_USERNAME);  
//env.put(Context.SECURITY_CREDENTIALS, LDAP_BIND_PASSWORD); 

当它们被取消注释时,程序将因相同的错误而失败。

但是,我仍然不知道如何使用 ldap(startTLS) 配置 gerrit。 有人遇到同样问题吗

© www.soinside.com 2019 - 2024. All rights reserved.