我在 tomcat 上有一个带有 ldap 的 java 应用程序,我可以毫无问题地进行身份验证。现在,我的公司要在ldap上插入ssl层,所以我需要使用ldaps。有什么建议可以忽略来自 ldaps 服务器的证书和信任证书吗?
这是我适用于 ldap 的代码
final String ldapAdServer = "ldap://my_ldap_url:3268";
final String ldapSearchBase = "Ldap_search_base";
//need a default user to be able to do query on AD
final String ldapUsername = "username_path_AD";
final String ldapPassword = "password_path_AD";
Hashtable<String, Object> env = new Hashtable<String, Object>();
env.put(Context.SECURITY_AUTHENTICATION, "simple");
if(ldapUsername != null) {
env.put(Context.SECURITY_PRINCIPAL, ldapUsername);
}
if(ldapPassword != null) {
env.put(Context.SECURITY_CREDENTIALS, ldapPassword);
}
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, ldapAdServer);
//ensures that objectSID attribute values
//will be returned as a byte[] instead of a String
env.put("java.naming.ldap.attributes.binary", "objectSID");
LdapContext ctx = new InitialLdapContext(env,null);
return ctx;
现在,我尝试创建此类来信任所有证书:
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
public class SSLFix {
public static void execute(){
TrustManager[] trustAllCerts = new TrustManager[] {
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkClientTrusted(X509Certificate[] arg0, String arg1)
throws CertificateException {}
@Override
public void checkServerTrusted(X509Certificate[] arg0, String arg1)
throws CertificateException {}
}
};
SSLContext sc=null;
try {
sc = SSLContext.getInstance("SSL");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
try {
sc.init(null, trustAllCerts, new java.security.SecureRandom());
} catch (KeyManagementException e) {
e.printStackTrace();
}
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
// Create all-trusting host name verifier
HostnameVerifier validHosts = new HostnameVerifier() {
@Override
public boolean verify(String arg0, SSLSession arg1) {
return true;
}
};
// All hosts will be valid
HttpsURLConnection.setDefaultHostnameVerifier(validHosts);
}
}
所以我决定用这个来改变我以前的 LDAP 代码:
public LdapContext getLDAPContext() throws NamingException
{
SSLFix.execute();
final String ldapAdServer = "ldaps://my_ldap_url:3269";
final String ldapSearchBase = "ldap_search_base";
//need a default user to be able to do query on AD
final String ldapUsername = "username_path_AD";
final String ldapPassword = "password_path_AD";
Hashtable<String, Object> env = new Hashtable<String, Object>();
env.put(Context.SECURITY_AUTHENTICATION, "simple");
if(ldapUsername != null) {
env.put(Context.SECURITY_PRINCIPAL, ldapUsername);
}
if(ldapPassword != null) {
env.put(Context.SECURITY_CREDENTIALS, ldapPassword);
}
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, ldapAdServer);
//ensures that objectSID attribute values
//will be returned as a byte[] instead of a String
env.put("java.naming.ldap.attributes.binary", "objectSID");
LdapContext ctx = new InitialLdapContext(env,null);
return ctx;
}
但是当我执行 ldaps 的控制时,我收到此错误:
javax.naming.CommunicationException:简单绑定失败:[根异常是 javax.net.ssl.SSLHandshakeException:sun.security.validator.ValidatorException:PKIX 路径构建失败:sun.security.provider.certpath.SunCertPathBuilderException:无法找到有效的达到请求目标的认证路径]
您必须将“LDAP-CA 证书”导入您的 Java 虚拟机。
为此,您可以运行:
keytool -import -trustcacerts -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit -alias ldap-CA -import -file ldap-ca-crt.pem
如果你的证书是好的。您的所有客户端(网络浏览器或移动 SO)在使用您的应用程序时都不会出现问题。
不要忘记导入中间证书或链式证书。(这些证书通常与 LDAP-CA 证书一起提供)
您可以创建自定义 X509TrustManager 或 SSLSocketFactory。
找到了两者的示例感谢大家的回复。我决定创建 X509TrustManager 和 SSLSocketFactory,因此允许所有证书。我用这种方式解决了我的问题
我不知道您的环境,但是您能否将发布LDAP证书的CA证书添加到您系统的可信CA中?
通过这种方式,您可以增强应用程序的安全性,否则使用 LDAP 几乎毫无用处。
我假设域控制器安装了一个CA服务器并且LDAP的证书是由它发布的。下载此证书并将其添加到您的环境中。
如果应用程序安装在域的计算机上,您可以共享 CA 证书并抛出组策略规则。您可以查看Microsoft 文档。域中的每个证书都必须由受信任的 CA 发布。
如果您无法接受此证书,请使用此answer中的选项 2。
将 CA 添加到证书存储中的问题是显而易见的。 1)它会起作用。 5年,也许8年。然后证书突然过期,一切,我指出——一切——都会消亡。你将会遭受全公司范围的灾难。
这没有任何意义。所有系统必须做的就像 ssh - 导入证书并报告其更改。
禁用证书验证的 LDAPS 比不加密的 LDAP 更好。
在某些情况下我们需要证书验证。例如,如果我们在数据传输中使用公共互联网,或者当我们没有好的方法来信任直接证书传递时。但是,这些并不常见。
问题是因为JAVA无法禁用证书验证,所以很多情况下我们不能使用LDAPS而必须使用不那么安全的LDAP。由于整个公司崩溃的风险太高,无法在受保护的网络内使用证书验证。所以我们需要一种方法来阻止这种检查,至少在必要时是这样。当它在两个不同的团体之间时这是可以的,但在内联网中绝对是糟糕的想法 - 因为从长远来看它太危险了。