authentication - 如何告诉具有多个证书的 LDAP SSL 服务器返回我需要的证书?

标签 authentication ssl active-directory ldap

我的简单 LDAP java 程序,使用

env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");  
env.put(Context.SECURITY_AUTHENTICATION, "simple");  
env.put(Context.SECURITY_PRINCIPAL, <UserDN>);  
env.put(Context.SECURITY_CREDENTIALS, <Password>);  
env.put(Context.SECURITY_PROTOCOL, "ssl");  
env.put(Context.PROVIDER_URL, "ldaps://<host>:636");  

使 LDAP SSL 身份验证停止工作,因为在我根本无权访问的服务器上安装了具有相同 CN 但主题中的其他详细信息不同的第二个服务器证书。

当我创建初始上下文时程序失败

new InitialDirContext(env);

错误是“无法初始化目录上下文::636


它在我运行时返回第二个服务器证书

openssl s_client -showcerts -connect <host>:636 </dev/null

这让我相信解决方案将是找到一种方法来告诉服务器要使用哪个证书。

我搜索并阅读了很多关于这个主题的文章,我不得不承认我很困惑,我不清楚这些文章是在谈论客户端证书还是服务器证书,或者要采取的行动是用于客户端或服务器端。

在一篇文章中,它说我可以使用带有 keystore 路径的自定义 SSLSocketFactory

env.put("java.naming.ldap.factory.socket", "com.xxx.MyCustomSSLSocketFactory");

但我不知道服务器上服务器证书 keystore 的路径。

在一篇 Microsoft 文章中,它说最好的解决方案是在服务器上只拥有一个服务器证书,或者将服务器证书放入 Active Directory 域服务 (NTDS\Personal) 证书存储区以进行 LDAPS 通信。但我无权访问服务器,必须在我的 LDAP java 程序中“修复”此问题。

在另一篇文章中,它说使用服务器名称指示 (SNI) 扩展。

那么有没有一种方法可以指定我想要给服务器的证书呢?还是我的问题出在其他地方?

非常感谢。


这是堆栈跟踪:

javax.naming.ServiceUnavailableException: <host>:636; socket closed
    at com.sun.jndi.ldap.Connection.readReply(Connection.java:419)
    at com.sun.jndi.ldap.LdapClient.ldapBind(LdapClient.java:340)
    at com.sun.jndi.ldap.LdapClient.authenticate(LdapClient.java:192)
    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.InitialContext.<init>(InitialContext.java:197)
    at javax.naming.directory.InitialDirContext.<init>(InitialDirContext.java:82)

当我使用 Jxplorer 运行相同的测试时,它给了我同样的错误。

EJP 指出问题是证书不受信任是正确的。非常感谢 EJP。

当我在 %JAVA_HOME%/lib/security/cacerts 中安装 CA 证书时,Jxplorer 起作用了。我的程序仍然失败。我必须在其中添加这些行才能使其正常工作(但不确定我是否需要所有这些...):

System.setProperty("javax.net.ssl.keyStore",%JAVA_HOME%/lib/security/cacerts);
System.setProperty("javax.net.ssl.trustStore",%JAVA_HOME%/lib/security/cacerts);
System.setProperty("javax.net.ssl.keyStorePassword=changeit);
System.setProperty("javax.net.ssl.trustStorePassword=changeit);

但由于证书首先不受信任,我只是“强制”我们的服务器信任它,因此这个解决方案是 Not Acceptable 。我们的服务器和 LDAP 服务器都没有运行 Java 7。所以 SNI 也出局了!

EJP 提到,如果服务器证书具有不同的算法或颁发者,我可以通过限制客户端(我的 webapp)中的密码套件或接受的颁发者来控制服务器证书。这 2 个证书确实有不同的颁发者,但是,我不知道该怎么做,也找不到任何关于它的信息。

EJP 能否请您详细说明,或指出一些网站...?

最佳答案

如果证书有不同的颁发者,您可以通过控制哪些颁发者在您的信任库中来控制您在客户端获得的证书。如果只有其中之一,那就是你会得到的。如果他们都在那里,你会得到运气。请注意,如果您的信任库还包含一个普通的 super 发行者,那么这可能又是运气。

关于authentication - 如何告诉具有多个证书的 LDAP SSL 服务器返回我需要的证书?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20156602/

相关文章:

android - 无法在 CouchbaseLiteHttpClientFactory Android 中添加 SSL 证书

azure - Mapr Streams to Azure 的 SSL 握手错误

powershell - 处理ForeignSecurityPrincipal

c# - 在 C# 中为用户创建 Exchange 邮箱

api - 如何在 Laravel 中进行 JWT cookie 身份验证

sql-server - SQL Server 2008 - 删除默认用户后添加 Windows 帐户

asp.net-mvc-4 - 注销后如何使http session 无效

.net - 如何获取Azure native 客户端应用程序角色?

c# - 获取无效 SSL 证书 (.NET) 的详细说明

Azure AD Connect 将电子邮件字段解析为新的 UPN