How to use wsimport when server expects client certificate?
Solution 1
You can call directly the WsImport java class (source) and add the JVM necessary args for Java knowing where to look for client certificates.
Something like
java -classpath C:\jdk160_29\lib\tools.jar -Djavax.net.ssl.trustStore=c:\jdk160_29\.mykeystore com.sun.tools.internal.ws.WsImport https://host:8443/Webservice?wsdl -p com.test -s ./src"
should do the trick.
Solution 2
I managed to do this by setting the _JAVA_OPTIONS environment variable with all the extra system properties to pass through; as a Windows batch file it looks like this (putting your password in as appropriate:
setlocal
set _JAVA_OPTIONS=%_JAVA_OPTIONS% -Djavax.net.ssl.trustStore="%JAVA_HOME%\jre\lib\security\cacerts" -Djavax.net.ssl.keyStoreType=PKCS12 -Djavax.net.ssl.keyStorePassword={...passwordForThePFX...} -Djavax.net.ssl.keyStore=r:\cert.pfx
wsimport -s . -verbose https://your.host.name/path/to/service?wsdl
endlocal
For sanity's sake, the Java options in the long 'set' line are:
-Djavax.net.ssl.trustStore="%JAVA_HOME%\jre\lib\security\cacerts"
-Djavax.net.ssl.keyStoreType=PKCS12
-Djavax.net.ssl.keyStorePassword={...passwordForThePFX...}
-Djavax.net.ssl.keyStore=R:\cert.pfx
You may or may not need to specift the trustStore
setting; I had to as I've got a couple of installs on and Java was picking up the wrong cacerts file for me.
Similarly you won't need the keyStorePassword
if the keystore isn't password protected. As for keyStoreType
, you'll need to specify this if you're not accessing a Java keystore.
Ultimately, the only "mandatory" option is the keyStore
which defines where the client certificate and keys live (and it's only mandatory if the client certificate isn't in any of the core Java certificate stores). As it stands, the example above is for a client certificate in a PFX file generated by exporting it from the Windows certificate store.
Solution 3
I found much easier (no need to play with -D, classpath, ...) to:
1. download the wsdl via ssl with your browser (install the certificate in your default browser by double-click on the keystore) or even easier with soapUI (install the keystore via config/ssl) that shows the wsdl contents
2. run the wsimport against the downloaded wsdl
That's all.
Cuga
Programming is easy. The challenge is in understanding the problem.
Updated on October 28, 2020Comments
-
Cuga over 3 years
I have a web service using mutual SSL authentication. I can access it just fine in the browser when I have the client's certificate installed.
I need to be able to access this using
wsimport
for generating the Java code to access the service.How can I set up my credentials so that I may access the URL using
wsimport
?Here's an example of what I'm trying, but it times out due to the inability to authenticate.
wsimport ./sample.wsdl -p com.company.ws.sample -Xnocompile -d ./src -extension -keep -XadditionalHeaders
Thanks for any help
Edit:
This is what
wsimport
prints. The WSDL is definitely valid, and at the given location, it's a matter of figuring out how to pass in my credentials for authenticating:wsimport https://wsdl.location.com?WSDL -p com.company.ws.sample -Xnocompile -d ./src -extension -keep -XadditionalHeaders parsing WSDL... [ERROR] Received fatal alert: handshake_failure Failed to read the WSDL document: "https://wsdl.location.com?WSDL", because 1) could not find the document; /2) the document could not be read; 3) the root element of the document is not <wsdl:definitions>. [ERROR] failed.noservice=Could not find wsdl:service in the provided WSDL(s): At least one WSDL with at least one service definition needs to be provided. Failed to parse the WSDL.
-
Chris J over 10 yearsFailed for me with a
Exception in thread "main" java.lang.NoSuchFieldError: theInstance
, however I've found an alternative. -
Madjosz over 5 yearsOne should add the option
-wsdllocation <actualWsdlLocationURI>
towsimport
because otherwise the generated webservice classes will point to the absolute local path of the wsdl. -
jgreen about 5 yearsThanks for this. In my case, I also needed to include -Djavax.net.ssl.trustStorePassword