1
我們正在使用LDAP(Active Directory)來驗證用戶。 ldap服務器是一個安全的服務器,所以我們生成了證書並添加到我們的密鑰庫中。要生成並導入我們就跟着證書:SSLHandshakeException當連接到LDAPS(活動目錄)
1. Retrieve the public CA certificate from the server
echo | openssl s_client -connect <host>:<port> 2>&1 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > ca-cert.cer
2. Import the certificate into the keystore.
sudo keytool -keystore <path-tojre>/jre/lib/security/cacerts -import -alias <name> -file ca-cert.crt
我們試着用下面的Java PROG驗證用戶時,出現SSL握手異常。如果我們嘗試驗證我們的LDAP服務帳戶/主用戶,它工作正常。以下是我們正在使用的代碼。
import java.util.Hashtable;
import javax.naming.AuthenticationException;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
public class LdapAuthenticationTest {
private final static String mstrUsersearchBase = ",OU=ServiceAccounts,DC=org,DC=com";
private final static String userSearchBase = ",ou=Staff,DC=org,DC=com";
private static final String MASTER_USER = "MASTER_ID"+mstrUsersearchBase;
private static final String MASTER_PASSWORD = "MASTER_PASSWORD";
private final static String ldapUrl = "ldaps://server:636";
static String appUser = "userId";
static String appUserpassword = "password";
public static void main(String[] args) {
String keystorePath = "/usr/lib/jvm/java-1.8.0-openjdk-1.8/jre/lib/security/cacerts";
System.setProperty("javax.net.ssl.trustStore", keystorePath);
// Password of your java keystore. Default value is : changeit
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
DirContext ctx = null;
try {
// 1. Authenticate using master user.
ctx = authenticate();
System.out.println("-------->>> FOUND MASTER ACCOUNT! <<<--------- ");
// 2. Authenticate using app user.
ctx = authenticate(appUser, appUserpassword);
System.out.println("-------->>> FOUND USER ACCOUNT! <<<--------");
ctx.close();
} catch (AuthenticationException ae) {
System.out.println(" Authentication failed - exception: " + ae);
} catch (Exception ie) {
System.err.println("Unable to get LDAP connection ----->>>>> " + ie);
}
}
private static DirContext authenticate() throws NamingException {
return authenticate(null, null);
}
private static DirContext authenticate(String username, String password) throws NamingException {
String userType = username != null ? "App user" : "Master user";
System.out.println("INSIDE Authenticate method: authenticating-> "+ userType);
String user = username != null ? username+userSearchBase : MASTER_USER;
String initialContextFactory = "com.sun.jndi.ldap.LdapCtxFactory";
String securityAuthentication = "simple";
Hashtable<String, String> env = new Hashtable<>();
env.put(Context.INITIAL_CONTEXT_FACTORY, initialContextFactory);
env.put(Context.SECURITY_AUTHENTICATION, securityAuthentication);
env.put(Context.PROVIDER_URL, ldapUrl);
String principal = "CN=" + user;
System.out.println("principal-> "+principal);
env.put(Context.SECURITY_PRINCIPAL, principal);
env.put(Context.SECURITY_CREDENTIALS, password != null ? password : MASTER_PASSWORD);
// Specify SSL
env.put(Context.SECURITY_PROTOCOL, "ssl");
DirContext ctx = new InitialDirContext(env);
return ctx;
}
}
我得到的日誌中控制檯:
-------->>> FOUND MASTER ACCOUNT! <<<---------
跟隨以下異常:
javax.naming.CommunicationException: simple bind failed: server:636 [Root exception is javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target]
的Java應用程序和LDAP服務器都在不同的機器上(Linux環境中)
檢查您的Java應用程序是否有權訪問頒發LDAPS證書的根CA. – Vesper
你的意思是使用TrustManager編寫程序並閱讀所有證書?我會看到一個示例代碼,因爲我不知道如何使用它。同時我用Debug = ALL選項運行應用程序。我發現無效的書面證書的原因類似於(未知證書),然後是closeSocket()調用。在此SSLHandshake異常之後。我懷疑它的閱讀密鑰庫,並找到其中一個證書無效關閉套接字。 – pranav
不,我的意思是檢查頒發LDAPS證書的CA根CA證書(或證書本身是否自簽名)存在於Java的證書存儲中,證書存儲又反過來呈現給驗證證書的應用程序。如果沒有,讓它存在。這些東西應該可以通過運行你的應用的PC上的Java控制面板來訪問。 – Vesper