How to use wsimport when server expects client certificate?

36,970

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.

Share:
36,970
Cuga
Author by

Cuga

Programming is easy. The challenge is in understanding the problem.

Updated on October 28, 2020

Comments

  • Cuga
    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
    Chris J over 10 years
    Failed for me with a Exception in thread "main" java.lang.NoSuchFieldError: theInstance, however I've found an alternative.
  • Madjosz
    Madjosz over 5 years
    One should add the option -wsdllocation <actualWsdlLocationURI> to wsimport because otherwise the generated webservice classes will point to the absolute local path of the wsdl.
  • jgreen
    jgreen about 5 years
    Thanks for this. In my case, I also needed to include -Djavax.net.ssl.trustStorePassword