I use SSL security in my Spring Boot application. While calling the address
final UriComponents uriComponents
= uriComponentsBuilder.path("/api/v1.0/register/token/{token}").buildAndExpand(token);
ResponseEntity<Boolean> response;
try {
response = restTemplate
.exchange(uriComponents.toUri(),
HttpMethod.PUT,
entity,
Boolean.class);
throw away me https://pastebin.com/A4Vb69hT carefully
I/O error on PUT request for "https://localhost:8443/api/v1.0/register/token/PBe3AzJ245W0sNyeg": java.security.cert.CertificateException: No name matching localhost found; nested exception is javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No name matching localhost found
I found on the Internet on the website http://java.globinch.com/enterprise-java/security/fix-java-security-certificate-exception-no-matching-localhost-found/
static {
//for localhost testing only
javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(
(hostname, sslSession) -> hostname.equals("localhost"));
}
after adding it, it receives further errors https://pastebin.com/kJZCqJ6K carefully
I/O error on PUT request for "https://localhost:8443/api/v1.0/register/token/EMNy7W9jJgsMWEn0z6hFOIHoB96zzSaeHWUs": sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target; nested 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
What should I do now?
I have two SSL files https://github.com/JonkiPro/REST-Web-Services/tree/master/src/main/resources/keystore
This answer is some kind of hack to run locally though enabling in actual environment will still work with certificates.
Just call SSLContextHelper.disable() before restTemplate.exchange
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import javax.security.cert.X509Certificate;
import org.apache.log4j.Logger;
public class SSLContextHelper {
private static final String KEY_STORE_TYPE="JKS";
private static final String CLASS_NAME=SSLContextHelper.class.getName();
private static final String TRANSPORT_SECURITY_PROTOCOL="TLS";
private static final Logger logger=Logger.getLogger(SSLContextHelper.class);
public static void enable(){
String keystoreType = "JKS";
InputStream keystoreLocation = null;
char [] keystorePassword = null;
char [] keyPassword = null;
try {
KeyStore keystore = KeyStore.getInstance(keystoreType);
keystore.load(keystoreLocation, keystorePassword);
KeyManagerFactory kmfactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmfactory.init(keystore, keyPassword);
InputStream truststoreLocation = null;
char [] truststorePassword = null;
String truststoreType = KEY_STORE_TYPE;
KeyStore truststore = KeyStore.getInstance(truststoreType);
truststore.load(truststoreLocation, truststorePassword);
TrustManagerFactory tmfactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyManager [] keymanagers = kmfactory.getKeyManagers();
TrustManager [] trustmanagers = tmfactory.getTrustManagers();
SSLContext sslContext = SSLContext.getInstance(TRANSPORT_SECURITY_PROTOCOL);
sslContext.init(keymanagers, trustmanagers, new SecureRandom());
SSLContext.setDefault(sslContext);
} catch (Exception e) {
logger.error(CLASS_NAME+"Exception in SSL "+e.getMessage());
e.printStackTrace();
}
}
public static void disable() {
try {
SSLContext sslc = SSLContext.getInstance("TLS");
TrustManager[] trustManagerArray = { (TrustManager) new NullX509TrustManager() };
sslc.init(null, trustManagerArray, null);
HttpsURLConnection.setDefaultSSLSocketFactory(sslc.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(new NullHostnameVerifier());
} catch(Exception e) {
e.printStackTrace();
}
}
private static class NullX509TrustManager implements X509TrustManager {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
System.out.println();
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
System.out.println();
}
}
private static class NullHostnameVerifier implements HostnameVerifier {
public boolean verify(String hostname, SSLSession session) {
return true;
}
}
The certificate of server is not a valid certificate chain or is probably self signed. Add the certificate to your trust store as trusted certificate ( do it only if you know it's a testing local certificate) and then try.
For details you can see https://eclipse-ee4j.github.io/mail/InstallCert
Certificate does not match the hostname, in this case localhost. please check that your self-signed certificate is using the right CN and if not recreate it.
Good article how to fix error :
http://java.globinch.com/enterprise-java/security/fix-java-security-certificate-exception-no-matching-localhost-found/
Related
I am creating a client and a server that connect via java SSL sockets. Only the server is authenticated (one-way authentication). After the client connects to the server, the client will prompt the user for a single line of input and send it to the server.
Whenever I run the client I get the following error:
Exception in thread "main" java.lang.IllegalStateException: KeyManagerFactoryImpl is not initialized
at sun.security.ssl.KeyManagerFactoryImpl.engineGetKeyManagers(KeyManagerFactoryImpl.java:51)
at javax.net.ssl.KeyManagerFactory.getKeyManagers(KeyManagerFactory.java:289)
at SSLClient.createSSLContext(SSLClient.java:43)
at SSLClient.main(SSLClient.java:50)
My Client code is:
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
public class SSLClient {
public static final int PORT_NO = 9020;
static void doProtocol( Socket cSock ) throws IOException
{
OutputStream out = cSock.getOutputStream();
InputStream in = cSock.getInputStream();
out.write("World".getBytes());
out.write('!');
int ch = 0;
while ((ch = in.read()) != '!')
{
System.out.print((char)ch);
}
System.out.println((char)ch);
}
static SSLContext createSSLContext() throws Exception
{
// set up a key manager for our local credentials
KeyManagerFactory mgrFact = KeyManagerFactory.getInstance("SunX509");
// KeyStore clientStore = KeyStore.getInstance("PKCS12");
// clientStore.load(new FileInputStream("client.p12"), "Password");
// mgrFact.init(clientStore, "password");
// create a context and set up a socket factory
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(mgrFact.getKeyManagers(), null, null);
return sslContext;
}
public static void main( String[] args ) throws Exception
{
SSLContext sslContext = createSSLContext();
SSLSocketFactory fact = sslContext.getSocketFactory();
// SSLSocketFactory fact = (SSLSocketFactory)SSLSocketFactory.getDefault();
SSLSocket cSock = (SSLSocket)fact.createSocket("localhost", PORT_NO);
doProtocol(cSock);
}
}
My Server code is:
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.KeyStore;
import java.security.Principal;
import java.util.Date;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManagerFactory;
import javax.security.auth.x500.X500Principal;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.crypto.tls.Certificate;
import org.bouncycastle.jcajce.provider.asymmetric.x509.KeyFactory;
public class SSLSocketServer {
public static int SERVER_PORT = 9020;
static boolean isEndEntity( SSLSession session ) throws SSLPeerUnverifiedException
{
Principal id = session.getPeerPrincipal();
if (id instanceof X500Principal)
{
X500Principal x500 = (X500Principal)id;
String Expireddate = x500.getName("Expireddate");
String Name = x500.getName("Name");
return (Name.equals("James") && Date.parse(Expireddate) > System.currentTimeMillis());
}
return false;
}
/**
* Carry out the '!' protocol - server side.
*/
static void doProtocol(
Socket sSock)
throws IOException
{
System.out.println("session started.");
InputStream in = sSock.getInputStream();
OutputStream out = sSock.getOutputStream();
// Send Key
out.write("Hello ".getBytes());
int ch = 0;
while ((ch = in.read()) != '!')
{
out.write(ch);
}
out.write('!');
sSock.close();
}
/**
* Create an SSL context with identity and trust stores in place
*/
SSLContext createSSLContext()
throws Exception
{
// set up a key manager for our local credentials
KeyManagerFactory mgrFact = KeyManagerFactory.getInstance("SunX509");
KeyStore serverStore = KeyStore.getInstance("JKS");
serverStore.load(new FileInputStream("server.jks"), "password".toCharArray());
mgrFact.init(serverStore, "password".toCharArray());
// set up a trust manager so we can recognize the server
TrustManagerFactory trustFact = TrustManagerFactory.getInstance("SunX509");
KeyStore trustStore = KeyStore.getInstance("JKS");
trustStore.load(new FileInputStream("trustStore.jks"), "trustpassword".toCharArray());
trustFact.init(trustStore);
// create a context and set up a socket factory
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(mgrFact.getKeyManagers(), trustFact.getTrustManagers(), null);
return sslContext;
}
public static void main( String[] args ) throws Exception
{
SSLServerSocketFactory fact = (SSLServerSocketFactory)SSLServerSocketFactory.getDefault();
SSLServerSocket sSock = (SSLServerSocket)fact.createServerSocket(SERVER_PORT);
SSLSocket sslSock = (SSLSocket)sSock.accept();
sSock.setNeedClientAuth(false); // current ignore
doProtocol(sslSock);
}
}
You will need to call one of the KeyManagerFactories init methods:
init(KeyStore ks, char[] password)
or
init(ManagerFactoryParameters spec)
prior to calling KeyManagerFactory.getKeyManagers() otherwise it will throw the observed IllegalStateException.
Your code could for example look somthing like this:
...
final KeyStore keyStore = KeyStore.getInstance("JKS");
try (final InputStream is = new FileInputStream(fullPathOfKeyStore())) {
keyStore.load(is, JKS_PASSWORD);
}
final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory
.getDefaultAlgorithm());
kmf.init(keyStore, KEY_PASSWORD);
...
See programcreek.com for full example.
I know that to load a certificate to use, I need to call KeyStore.load(InputStream, char[]);. How could I load the certificate on the client side if I need the password? I don't need this when connecting to Google, but I want to use Trust Managers to validate Google certificates. I also cannot make a SSLServerSocket and connect to it without loading a certificate.
EDIT: Added code:
package testing;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
public class SSLClientTest {
public static void main(String[] args) {
int port = 443;
String host = "google.com";
try {
SSLContext sc = SSLContext.getInstance("TLSv1.2");
KeyStore ks = KeyStore.getInstance("JKS");
InputStream ksIs = new FileInputStream("securecert.certificate");
try {
ks.load(ksIs, "pwdpwdpwd".toCharArray());
} finally {
if (ksIs != null) {
ksIs.close();
}
}
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, "pwdpwdpwd".toCharArray());
sc.init(kmf.getKeyManagers(),
new TrustManager[] { new MyTrustManager() }, null);
SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory
.getDefault();
SSLSocket socket = (SSLSocket) factory.createSocket(host, port);
socket.startHandshake();
BufferedReader in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
System.out.println(in.readLine());
in.close();
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private static final class MyTrustManager implements X509TrustManager {
#Override
public void checkClientTrusted(X509Certificate[] arg0, String arg1)
throws CertificateException {
}
#Override
public void checkServerTrusted(X509Certificate[] arg0, String arg1)
throws CertificateException {
}
#Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[] {};
}
}
}
Note that I have to load the certificate, securecert.certificate, at the like of code ks.load(InputStream, char[]); I of course know the password, but what if I don't? Then how could I validate the certificate with a trust manager? This code simply locks. Please answer. Thanks!
Seems that you need a client authentication through SSL and you want let the user enter the password for his keystore. Based on your explanation I suppose that each installed client has its own keystore from a local path (If not the question has nonsense because if the keystore is always the same you don't need to pass a different password each time... however if this is the case you've to check if this client it's secure).
So to let the user enter a password you can instantiate the keystore in a different way instead of using KeyStore.getInstance(InputStream, Char[]), you can use KeyStore.Builder.newInstance and KeyStore.CallbackHandlerProtection methods, and you have to create a class which implements javax.security.auth.callback.CallbackHandler, this class have to override handle() method for example using swing or awt panel to let the user introduce the password. Below I show you some sample code to guide you through this steps:
Load the keystore
import java.io.File;
import java.security.KeyStore;
import java.security.Provider;
import java.util.Enumeration;
public class KeyStoreCallbackSample {
public static void main(String args[]) throws Exception {
// instantiate a keystore to get the provider for specific type
KeyStore ks = KeyStore.getInstance("JKS");
// create the callback handler to get the password
KeyStore.CallbackHandlerProtection cbhp = new KeyStore.CallbackHandlerProtection(new YourImplementationCallbackHander());
// create the builder passing keystoreType, provider, keystore file, and callbackhandler
KeyStore.Builder builder = KeyStore.Builder.newInstance("JKS", ks.getProvider(), new File("/path/YourKeyStore.jks"), cbhp);
// create the keystore
ks = builder.getKeyStore();
// print the keystores alias to check if all it's load correctly
Enumeration<String> aliases = ks.aliases();
while(aliases.hasMoreElements()){
System.out.println(aliases.nextElement());
}
}
}
CallbackHandler implementation
import java.io.IOException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
/**
* PIN handler for keystores
*/
public class PinInputHandler implements CallbackHandler {
private char[] lastPassword;
public PinInputHandler(){}
// implement this method to handle the callback
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
for (Callback cb : callbacks) {
if (cb instanceof javax.security.auth.callback.PasswordCallback) {
javax.security.auth.callback.PasswordCallback pcb = (javax.security.auth.callback.PasswordCallback) cb;
try {
this.lastPassword = // HERE YOUR SWING OR AWT OR ANOTHER WAY TO GET THE PASSWORD FROM THE CLIENT
} catch (Exception e) {}
pcb.setPassword(this.lastPassword);
}
}
}
}
If you need more info you can check at KeyStore, KeyStore.Builder, KeyStore.CallbackHandlerProtection and CallbackHandlerdocumentation.
Hope this helps,
I have a cxf service running at
https://localhost:8443/services/MyService?wsdl
with client certificate required. The WSDL is not important here.
I am able to invoke the service when I remove the client certificate or https requirement.
The service and client classes were generated with cxf wsdl2java utility.
Here is MyService.class:
package com.mycompany;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import javax.xml.ws.WebEndpoint;
import javax.xml.ws.WebServiceClient;
import javax.xml.ws.WebServiceFeature;
/**
* This class was generated by Apache CXF 2.7.3 2013-03-29T13:59:37.423-03:00 Generated source version: 2.7.3
*/
#WebServiceClient(name = "MyService", wsdlLocation = "myservice.wsdl", targetNamespace = "http://server/schemas/services")
public class MyService extends Service {
public final static URL WSDL_LOCATION;
public final static QName SERVICE = new QName("http://server/schemas/services", "MyService");
public final static QName MyServicePort = new QName("http://server/schemas/services", "MyServicePort");
static {
URL url = MyService.class.getResource("myservice.wsdl");
if (url == null) {
Logger.getLogger(MyService.class.getName()).log(Level.INFO, "Can not initialize the default wsdl from {0}", "myservice.wsdl");
}
WSDL_LOCATION = url;
}
public MyService(URL wsdlLocation) {
super(wsdlLocation, SERVICE);
}
public MyService(URL wsdlLocation, QName serviceName) {
super(wsdlLocation, serviceName);
}
public MyService() {
super(WSDL_LOCATION, SERVICE);
}
/**
*
* #return returns EncaminharMensagemPortType
*/
#WebEndpoint(name = "MyServicePort")
public MyServicePortType getMyServicePort() {
return super.getPort(MyServicePort, MyServicePortType.class);
}
/**
*
* #param features
* A list of {#link javax.xml.ws.WebServiceFeature} to configure on the proxy. Supported features not in the
* <code>features</code> parameter will have their default values.
* #return returns EncaminharMensagemPortType
*/
#WebEndpoint(name = "MyServicePort")
public MyServicePortType getMyServicePort(WebServiceFeature... features) {
return super.getPort(MyServicePort, MyServicePortType.class, features);
}
}
Here is my client without client certificate requirement: (that work fine)
package com.mycompany;
import java.net.URL;
import javax.xml.namespace.QName;
import com.mycompany.IdHolder;
import com.mycompany.MyDataObject;
public class CxfClientSslTest {
public static void main(String[] args) {
try {
QName SERVICE_NAME = new QName("http://server/schemas/services", "MyService");
URL wsdlURL = new URL("https://localhost:8443/services/MyService?wsdl");
MyService ss = new MyService(wsdlURL, SERVICE_NAME);
MyServicePortType port = ss.getMyServicePort();
IdHolder mensagem = new IdHolder();
mensagem.setId(1L);
MyDataObject dataObject = port.getById(mensagem);
System.out.println("Id: " + dataObject.getId());
} catch (Exception e) {
e.printStackTrace();
}
}
}
And here is my client send his certificate:
package com.mycompany;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.xml.namespace.QName;
import org.apache.cxf.configuration.jsse.TLSClientParameters;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.transport.http.HTTPConduit;
public class CxfClientSslTest {
public static void main(String[] args) {
try {
QName SERVICE_NAME = new QName("http://server/schemas/services", "MyService");
URL wsdlURL = new URL("https://localhost:8443/services/MyService?wsdl");
MyService ss = new MyService(wsdlURL, SERVICE_NAME);
MyServicePortType port = ss.getMyServicePort();
tslIt(port);
IdHolder mensagem = new IdHolder();
mensagem.setId(1L);
MyDataObject dataObject = port.getById(mensagem);
System.out.println("Id: " + dataObject.getId());
} catch (Exception e) {
e.printStackTrace();
}
}
public static void tslIt(MyServicePortType port) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException,
UnrecoverableKeyException {
Client client = ClientProxy.getClient(port);
HTTPConduit http = (HTTPConduit) client.getConduit();
TLSClientParameters tlsClientParameters = http.getTlsClientParameters();
KeyStore keyStore = getKeyStore();
KeyStore trustStore = getTrustStore();
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, "123456".toCharArray());
KeyManager[] keyMgrs = keyManagerFactory.getKeyManagers();
tlsClientParameters.setKeyManagers(keyMgrs);
trustManagerFactory.init(trustStore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
tlsClientParameters.setTrustManagers(trustManagers);
tlsClientParameters.setDisableCNCheck(true);
}
public static KeyStore getKeyStore() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
URL keyStoreUrl = CxfClientSslTest.class.getResource("/certs/client.jks");
File keystoreFile = new File(keyStoreUrl.getPath());
if (!keystoreFile.exists()) {
throw new RuntimeException("keystore doesn't exists: " + keystoreFile.getAbsolutePath());
}
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream keystoreInput = new FileInputStream(keystoreFile.getAbsolutePath());
keystore.load(keystoreInput, "changeit".toCharArray());
keystoreInput.close();
return keystore;
}
public static KeyStore getTrustStore() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
URL trustStoreUrl = CxfClientSslTest.class.getResource("/certs/client-trust.jks");
File trustStoreFile = new File(trustStoreUrl.getPath());
if (!trustStoreFile.exists()) {
throw new RuntimeException("truststore doesn't exists: " + trustStoreFile.getAbsolutePath());
}
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream trustStoreInput = new FileInputStream(trustStoreFile.getAbsolutePath());
trustStore.load(trustStoreInput, "changeit".toCharArray());
trustStoreInput.close();
return trustStore;
}
}
The TLS configuration both from client and server were checked and are ok. But when I run the program I get this:
Information: Can not initialize the default wsdl from myservice.wsdl
javax.xml.ws.WebServiceException: org.apache.cxf.service.factory.ServiceConstructionException: Failed to create service.
at org.apache.cxf.jaxws.ServiceImpl.<init>(ServiceImpl.java:149)
at org.apache.cxf.jaxws.spi.ProviderImpl.createServiceDelegate(ProviderImpl.java:98)
at javax.xml.ws.Service.<init>(Service.java:77)
at com.mycompany.MyService.<init>(MyService.java:36)
at com.mycompany.CxfClientSslTest.main(CxfClientSslTest.java:32)
Caused by: org.apache.cxf.service.factory.ServiceConstructionException: Failed to create service.
at org.apache.cxf.wsdl11.WSDLServiceFactory.<init>(WSDLServiceFactory.java:100)
at org.apache.cxf.jaxws.ServiceImpl.initializePorts(ServiceImpl.java:199)
at org.apache.cxf.jaxws.ServiceImpl.<init>(ServiceImpl.java:147)
... 4 more
Caused by: javax.wsdl.WSDLException: WSDLException: faultCode=PARSER_ERROR: Problem parsing 'https://localhost:8443/services/MyService?wsdl'.: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No name matching localhost found
at com.ibm.wsdl.xml.WSDLReaderImpl.getDocument(Unknown Source)
at com.ibm.wsdl.xml.WSDLReaderImpl.readWSDL(Unknown Source)
at com.ibm.wsdl.xml.WSDLReaderImpl.readWSDL(Unknown Source)
at org.apache.cxf.wsdl11.WSDLManagerImpl.loadDefinition(WSDLManagerImpl.java:262)
at org.apache.cxf.wsdl11.WSDLManagerImpl.getDefinition(WSDLManagerImpl.java:205)
at org.apache.cxf.wsdl11.WSDLServiceFactory.<init>(WSDLServiceFactory.java:98)
... 6 more
Caused by: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No name matching localhost found
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1868)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:276)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:270)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1337)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:154)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:868)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:804)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:998)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1294)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1321)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1305)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:523)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1296)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(XMLEntityManager.java:653)
at com.sun.org.apache.xerces.internal.impl.XMLVersionDetector.determineDocVersion(XMLVersionDetector.java:189)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:799)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:764)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:123)
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:240)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:300)
... 12 more
Caused by: java.security.cert.CertificateException: No name matching localhost found
at sun.security.util.HostnameChecker.matchDNS(HostnameChecker.java:208)
at sun.security.util.HostnameChecker.match(HostnameChecker.java:93)
at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:347)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:203)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:126)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1319)
... 30 more
I can see that the problem is happening before my https configuration get done, when cxf tries to download the wsdl.
I made a research on how to make cxf use that https configuration to download the wsdl. It take me a lot of time, but I can't find the answer out there.
So my question is: how to make cxf use the https configuration to download the wsdl?
Please, I have the answer already and I intend to put it here. So, if you don't have a good answer, or better the answer, please don't post one.
After a lot of research on the web without success, I decide it is time to debug the cxf API. That is one of the points of open source, right?
So I found out that cxf don't download directly the wsdl. It delegates that to wsdl4j through the call of
javax.wsdl.xml.WSDLReader.readWSDL(javax.wsdl.xml.WSDLLocator)
which calls
javax.wsdl.xml.WSDLLocator.getBaseInputSource()
which calls
org.apache.cxf.wsdl11.ResourceManagerWSDLLocator.getInputSource(String, String)
because ResourceManagerWSDLLocator were the WSDLLocator of the first method call.
ResourceManagerWSDLLocator.getInputSource first line is:
InputStream ins = bus.getExtension(ResourceManager.class).getResourceAsStream(importLocation);
Now as ResourceManager is a extension of xcf's Bus, and you can add more ResourceResolver to it and the DefaultResourceManager (implements ResourceManager) will loop through all registered resolvers and will use the first one resolving a non-null value, you just need add a ResourceResolver to the ResourceManager.
My final and working client application is:
package com.mycompany;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.xml.namespace.QName;
import org.apache.cxf.Bus;
import org.apache.cxf.BusFactory;
import org.apache.cxf.configuration.jsse.TLSClientParameters;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.resource.ResourceManager;
import org.apache.cxf.resource.ResourceResolver;
import org.apache.cxf.transport.http.HTTPConduit;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.BasicClientConnectionManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
public class CxfClientSslTest {
public static void main(String[] args) {
try {
Bus bus = BusFactory.getThreadDefaultBus();
ResourceManager extension = bus.getExtension(ResourceManager.class);
extension.addResourceResolver(new ResourceResolver() {
#Override
public <T> T resolve(String resourceName, Class<T> resourceType) {
System.out.println("resourceName: " + resourceName + " - resourceType: " + resourceType);
return null;
}
#Override
public InputStream getAsStream(String name) {
try {
if (!name.startsWith("https")) {
return null;
}
SSLSocketFactory sslSocketFactory = SslUtil.getSslSocketFactory();
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("https", 8443, sslSocketFactory));
final HttpParams httpParams = new BasicHttpParams();
DefaultHttpClient httpClient = new DefaultHttpClient(new BasicClientConnectionManager(schemeRegistry), httpParams);
HttpGet get = new HttpGet(name);
HttpResponse response = httpClient.execute(get);
return response.getEntity().getContent();
} catch (Exception e) {
return null;
}
}
});
QName SERVICE_NAME = new QName("http://server/schemas/services", "MyService");
URL wsdlURL = new URL("https://localhost:8443/services/MyService?wsdl");
MyService ss = new MyService(wsdlURL, SERVICE_NAME);
MyServicePortType port = ss.getMyServicePort();
tslIt(port);
IdHolder mensagem = new IdHolder();
mensagem.setId(1L);
MyDataObject dataObject = port.getById(mensagem);
System.out.println("Id: " + dataObject.getId());
} catch (Exception e) {
e.printStackTrace();
}
}
public static void tslIt(MyServicePortType port) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException,
UnrecoverableKeyException {
Client client = ClientProxy.getClient(port);
HTTPConduit http = (HTTPConduit) client.getConduit();
TLSClientParameters tlsClientParameters = http.getTlsClientParameters();
KeyStore keyStore = getKeyStore();
KeyStore trustStore = getTrustStore();
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, "123456".toCharArray());
KeyManager[] keyMgrs = keyManagerFactory.getKeyManagers();
tlsClientParameters.setKeyManagers(keyMgrs);
trustManagerFactory.init(trustStore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
tlsClientParameters.setTrustManagers(trustManagers);
tlsClientParameters.setDisableCNCheck(true);
}
public static KeyStore getKeyStore() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
URL keyStoreUrl = CxfClientSslTest.class.getResource("/certs/client.jks");
File keystoreFile = new File(keyStoreUrl.getPath());
if (!keystoreFile.exists()) {
throw new RuntimeException("keystore doesn't exists: " + keystoreFile.getAbsolutePath());
}
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream keystoreInput = new FileInputStream(keystoreFile.getAbsolutePath());
keystore.load(keystoreInput, "changeit".toCharArray());
keystoreInput.close();
return keystore;
}
public static KeyStore getTrustStore() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
URL trustStoreUrl = CxfClientSslTest.class.getResource("/certs/client-trust.jks");
File trustStoreFile = new File(trustStoreUrl.getPath());
if (!trustStoreFile.exists()) {
throw new RuntimeException("truststore doesn't exists: " + trustStoreFile.getAbsolutePath());
}
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream trustStoreInput = new FileInputStream(trustStoreFile.getAbsolutePath());
trustStore.load(trustStoreInput, "changeit".toCharArray());
trustStoreInput.close();
return trustStore;
}
}
I think the standard way in apache cxf is to set-up an http conduit in your cxf.xml refering to your jks keystore:
<http:conduit id="{Namespace}PortName.http-conduit">
<http:tlsClientParameters>
...
<sec:trustManagers>
<sec:keyStore type="JKS"
password="StorePass"
file="certs/truststore.jks"/>
</sec:trustManagers>
...
</http:tlsClientParameters>
</http:conduit>
More information here: Configuring SSL support
tlsClientParameters.setUseHttpsURLConnectionDefaultSslSocketFactory(false);
Above line is required to disable default SslSocketFactory (which will ignore the keyStore and trustStore configured in tlsClientParamters)
Adding to reply https://stackoverflow.com/a/15755512/19664676
by #DiogoSantana
One can simply add HTTPConduitConfigurer extension to bus like this.
package com.mycompany;
import com.mycompany.IdHolder;
import com.mycompany.MyDataObject;
import org.apache.cxf.Bus;
import org.apache.cxf.BusFactory;
import org.apache.cxf.configuration.jsse.TLSClientParameters;
import org.apache.cxf.transport.http.HTTPConduit;
import org.apache.cxf.transport.http.HTTPConduitConfigurer;
import java.net.URL;
import java.security.SecureRandom;
import javax.net.ssl.SSLContext;
import javax.xml.namespace.QName;
public class CxfClientSslTest {
public static void main(String[] args) {
Bus bus = BusFactory.getThreadDefaultBus();
bus.setExtension(new HTTPConduitConfigurer() {
#Override
public void configure(String name, String address, HTTPConduit c) {
//crate and configure sslcontext
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(getKeyManagers(), getTrustManagers(), new SecureRandom());
TLSClientParameters tls = new TLSClientParameters();
//configure tls client params here
tls.setSSLSocketFactory(sslContext.getSocketFactory());
//set tls client params
c.setTlsClientParameters(tls);
}
}, HTTPConduitConfigurer.class);
QName SERVICE_NAME = new QName("http://server/schemas/services", "MyService");
URL wsdlURL = new URL("https://localhost:8443/services/MyService?wsdl");
MyService ss = new MyService(wsdlURL, SERVICE_NAME);
MyServicePortType port = ss.getMyServicePort();
IdHolder mensagem = new IdHolder();
mensagem.setId(1L);
MyDataObject dataObject = port.getById(mensagem);
System.out.println("Id: " + dataObject.getId());
}
}
javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No name matching localhost found
Above exception happens When you create your self-signed certificate with your name,
To resolve this exception, you need to add "localhost" on the following step
What is your first and last name?
[Unknown]: localhost
I need to extract expiration date from SSL certificate on web site in Java,should support both
trusted and self-signed certificate,such as:
1.trusted
https://github.com
2.self-signed
https://mms.nw.ru/
I already copy some code as:
import java.net.URL;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
public class SSLTest {
public static void main(String [] args) throws Exception {
// configure the SSLContext with a TrustManager
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(new KeyManager[0], new TrustManager[] {new DefaultTrustManager()}, new SecureRandom());
SSLContext.setDefault(ctx);
URL url = new URL("https://github.com");//https://mms.nw.ru
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setHostnameVerifier(new HostnameVerifier() {
#Override
public boolean verify(String arg0, SSLSession arg1) {
return true;
}
});
System.out.println(conn.getResponseCode());
Certificate[] certs = conn.getServerCertificates();
for (Certificate cert :certs){
System.out.println(cert.getType());
System.out.println(cert);
}
conn.disconnect();
}
private static class DefaultTrustManager implements X509TrustManager {
#Override
public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}
#Override
public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}
#Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
}
The questions are:
How to parse the expiration date from the certificate, in my code the toString() did output the date,but it is hard to parse.
How to determine the certificate chain, eg, the github certificate with chains 3, how did i know which certificate to get the expiration date from?
How to parse the expiration date from the certificate
Cast it to an X509Certificate and call getNotAfter().
How to determine the certificate chain, eg, the github certificate with chains
You've got it. That's what the Certificate[] array is, as it says in the Javadoc.
How did i know which certificate to get the expiration date from?
Read the Javadoc. "The peer's own certificate first followed by any certificate authorities".
However I don't know why you're doing any of this. Java should already do it all for you.
And please throw away that insecure and incorrect TrustManager implementation. The correct way to handle self-signed certificates is to import them into the client truststore. Please also throw away your insecure HostnameVerifier, and use the default one, or a secure one. Why use HTTPS at all if you don't want it to be secure?
Make sure you append Begin/End lines to PEM format otherwise java does not understand it.
public class CertTest {
public static final String cert = "-----BEGIN CERTIFICATE-----\n<CERT_DATA>\n-----END CERTIFICATE-----";
public static void main(String[] args){
try {
X509Certificate myCert = (X509Certificate)CertificateFactory
.getInstance("X509")
.generateCertificate(
// string encoded with default charset
new ByteArrayInputStream(cert.getBytes())
);
System.out.println(myCert.getNotAfter());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
In Kotlin way, it should look something like this:
fun certInformation(aURL: String) {
val destinationURL = URL(aURL)
val conn = destinationURL.openConnection() as HttpsURLConnection
conn.connect()
val certs = conn.serverCertificates
for (cert in certs) {
println("Certificate is: $cert")
if (cert is X509Certificate) {
println(cert.issuerDN.name)
println(cert.notAfter)
println(cert.notBefore)
}
}
}
am trying to change the truststore path dynamically using java web application.
am developing struts application and login is based on ldap through secure socket layer (ssl) connection.
To connect with ssl i have created .cer file using java keytool option.
Now i able to connect with ldap and i can retieve user information from ldap.
when i change the ssl certificate(invalid certificate for testing) dynamically it could not give any exceptions. but it works when i restart the tomcat
server.
following is the code that i am trying
try{
java.io.InputStream in = new java.io.FileInputStream("C:\\test.cer");
java.security.cert.Certificate c = java.security.cert.CertificateFactory.getInstance("X.509").generateCertificate(in);
java.security.KeyStore ks = java.security.KeyStore.getInstance("JKS");
ks.load(null);
if (!ks.containsAlias("alias ldap")) {
ks.setCertificateEntry("alias ldap", c);
}
java.io.OutputStream out = new java.io.FileOutputStream("C:\\ldap.jks");
char[] kspass = "changeit".toCharArray();
ks.store(out, kspass);
out.close();
System.setProperty("javax.net.ssl.trustStore", "C:\\ldap.jks");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
}catch(Exception e){
e.printStackTrace();
}
is there any mistake that i made with the code?
does any new code that i need to put to connect dynamically?
Note :
instead of c:\ldap.jks file i gave invalid file dynamically. it does not give any exception.
Edited (checked with custom TrustManager) :
i also implemented TrustManager and ssl context is initialized with custom trust manager.
but i am not able to get the expected behaviour
could u please help me. the code that i tried is
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.UUID;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
public class TestDynamicSSLCert {
public static void main(String[] args)throws NamingException,IOException {
DataInputStream din = new DataInputStream (System.in);
String yes = "yes";
String certpath = "C:\\cert.cer";
String ldappath1 = "C:\\ldap.jks";
String ldappath2 = "C:\\ldap.jks"; // setting valid key store path
while("yes".equalsIgnoreCase(yes.trim())){
System.out.println(" ldappath2 : "+ldappath2);
Hashtable env = new Hashtable();
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL,"uid=admin,ou=system");
env.put(Context.SECURITY_CREDENTIALS, "secret");
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldaps://172.16.12.4:636/ou=system");
try {
java.io.InputStream in = new java.io.FileInputStream(certpath);
java.security.cert.Certificate c = java.security.cert.CertificateFactory.getInstance("X.509").generateCertificate(in);
java.security.KeyStore ks = java.security.KeyStore.getInstance("JKS");
ks.load(null);
if (!ks.containsAlias("alias ldap")) {
ks.setCertificateEntry("alias ldap", c);
}
java.io.OutputStream out = new java.io.FileOutputStream(ldappath1);
char[] kspass = "changeit".toCharArray();
ks.store(out, kspass);
out.close();
System.setProperty("javax.net.ssl.trustStore", ldappath2);
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
// Custorm trust manager
MyX509TrustManager reload = new MyX509TrustManager(ldappath2,c);
TrustManager[] tms = new TrustManager[] { reload };
javax.net.ssl.SSLContext sslCtx = javax.net.ssl.SSLContext.getInstance("SSL");
sslCtx.init(null, tms, null);
// Custom trust manager
} catch (Exception e) {
e.printStackTrace();
}
DirContext ctx = new InitialDirContext(env);
NamingEnumeration enm = ctx.list("");
while (enm.hasMore()) {
System.out.println(enm.next());
}
ctx.close();
System.out.println(" Go again by yes/no :");
yes = din.readLine();
ldappath2 = "C:\\invalidldap.jks"; // setting invalid keystore path
}
}
}
class MyX509TrustManager implements X509TrustManager {
private final String trustStorePath;
private X509TrustManager trustManager;
private List<Certificate> tempCertList = new ArrayList<Certificate>();
public MyX509TrustManager(String tspath,Certificate cert)throws Exception{
this.trustStorePath = tspath;
tempCertList.add(cert);
reloadTrustManager();
}
public MyX509TrustManager(String tspath)
throws Exception {
this.trustStorePath = tspath;
reloadTrustManager();
}
#Override
public void checkClientTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
trustManager.checkClientTrusted(chain, authType);
}
#Override
public void checkServerTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
try {
trustManager.checkServerTrusted(chain, authType);
} catch (CertificateException cx) {
addServerCertAndReload(chain[0], true);
trustManager.checkServerTrusted(chain, authType);
}
}
#Override
public X509Certificate[] getAcceptedIssuers() {
X509Certificate[] issuers = trustManager.getAcceptedIssuers();
return issuers;
}
private void reloadTrustManager() throws Exception {
// load keystore from specified cert store (or default)
KeyStore ts = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream in = new FileInputStream(trustStorePath);
try {
ts.load(in, null);
} finally {
in.close();
}
// add all temporary certs to KeyStore (ts)
for (Certificate cert : tempCertList) {
ts.setCertificateEntry(UUID.randomUUID().toString(), cert);
}
// initialize a new TMF with the ts we just loaded
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ts);
// acquire X509 trust manager from factory
TrustManager tms[] = tmf.getTrustManagers();
for (int i = 0; i < tms.length; i++) {
if (tms[i] instanceof X509TrustManager) {
trustManager = (X509TrustManager) tms[i];
return;
}
}
throw new NoSuchAlgorithmException("No X509TrustManager in TrustManagerFactory");
}
private void addServerCertAndReload(Certificate cert,
boolean permanent) {
try {
if (permanent) {
// import the cert into file trust store
// Google "java keytool source" or just ...
Runtime.getRuntime().exec("keytool -importcert ...");
} else {
tempCertList.add(cert);
}
reloadTrustManager();
} catch (Exception ex) { /* ... */ }
}
}
Expected Behaviour :
ldap connection should be successfull with valid keystore file (during first loop ).
if user give yes then invalid keystore is assigned and need to produce exception and should not connect to ldap
Actual Behaviour:
for both valid keystore file i able to retrieve information from ldap.
Note :
if i set String ldappath2 = "C:\invalidldap.jks"; at begining, it gives exception.
Why am doing this ?
#EJP, because, i need to develope module which is based on ldap authentication securely. module should support multiple ldap servers. ldap settings can be inserted from the UI (webpage that has the ui to get the details like ldaphost, port, basedn, and ssl certificate) and this details should go to database. at the same time certificate also present in database. work for module is just retrieve the users from ldap and store it to another table. so if we change the new ldap server setting with new certificate means, System.setProperty("javax.net.ssl.trustStore","truststorepath") will fail. are you okay with my explanation?
You are correct. You have to restart Tomcat when you change the keystore or truststore. You don't need to write code to load client certificates, you just need to make sure you are dealing with servers whose certificates are signed by a CA that you trust. Adding new certificates at runtime is radically insecure.
Is there any other way to connect ldap securely with out using above
steps?
Yes, but why do you think you need to know?
Does the application (tomcat or single java file) should be restarted
whenever trustStore property is updated ?
Yes.