3

I'm having trouble sending off a simple SOAP request and getting a response inside my java project.

I'm still fairly new to doing this via java so I've been looking at this tutorial since I'm also using spring-boot in the rest of my project.

Currently I'm getting this error (I did have to remove specifics due to being company related and replace with generic strings for the sake of pasting them here. I had to remove my actual wsdl and the actual hostname):

[INFO] --- maven-jaxb2-plugin:0.12.3:generate (default) @ dcc-vm-validation ---
[INFO] Up-to-date check for source resources [[myWsdl, file:pom.xml]] and taret resources [[]].
[WARNING] The URI [myWsdl] seems to represent an absolute HTTP or HTTPS URL. Getting the last modification timestamp is only possible if the URL is accessible and if the server returns the [Last-Modified] header correctly. This method is not reliable and is likely to fail. In this case the last modification timestamp will be assumed to be unknown.
[ERROR] Could not retrieve the last modification timestamp for the URI [myWsdl] from the HTTP URL connection. The [Last-Modified] header was probably not set correctly.
[WARNING] Last modification of the URI [myWsdl] is not known.
[INFO] Sources are not up-to-date, XJC will be executed.
[ERROR] Error while parsing schema(s).Location [].
com.sun.istack.SAXParseException2; IOException thrown when processing "myWsdl". Exception: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No name matching hostname found.

Here is my "build" section of my pom:

<build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>

            <plugin>
                <groupId>org.jvnet.jaxb2.maven2</groupId>
                <artifactId>maven-jaxb2-plugin</artifactId>
                <version>0.12.3</version>

                <executions>
                    <execution>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                    </execution>
                </executions>

                <configuration>
                    <schemaLanguage>WSDL</schemaLanguage>
                    <generatePackage>package.wsdl</generatePackage>

                    <schemas>
                        <schema>
                            <url>myWsdl</url>
                        </schema>
                    </schemas>
                </configuration>
            </plugin>
        </plugins>
    </build>

After doing some research on what this specific error means I was able to download the self-signed cert from the wsdl location (via Chrome) to my desktop. I then used keytool to add this specific cert to my cacerts file (I made sure that the cert alias matched the hostname in the error above). As far as I was told, this would fix my connection issues but it didn't. I'm still seeing the same error as above saying that it can't find my hostname.

What am I missing here?

Alternatively, I also read about bypassing certs altogether. This is also an approach I wouldn't be opposed to since this project I'm working on is ONLY internal and will be located on the company intranet. It won't be accessible by anybody other than employees so the security risks can essentially be ignored. I know this is considered bad practice but I've already read the risks and discussed it with my boss and he's fine if we go this route as well.

I was able to find this little snippet of code that seems to do the job:

static {
            javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(new javax.net.ssl.HostnameVerifier() {
                public boolean verify(String hostname, javax.net.ssl.SSLSession session) {
                    if (hostname.equals(myHostname)) {
                        return  true;
                    }

                    return false;
                }
            });
        }

but in all the examples I found it never once specified where to put it. It just said that this is what you need to ignore SSL and self-signed cert errors. Where would I put this in correlation to my code and is there a specific way to do this since I'm attempting to do it via spring / jaxb?

Sorry for the long winded wall! Just trying to learn something new over here :)

user1818298
  • 509
  • 2
  • 8
  • 23
  • Are you able to do request response from a different client for example POSTMAN or SOAPUI or Boomerang? – Mukul Tripathi Oct 11 '16 at 14:35
  • Yes. I'm actually able to send a request and get a valid response with both SoapUI and Postman. I tried to mirror the headers correctly in the java code since there is basic authorization that happens as well but I'm not sure I'm even hitting that part yet when I'm getting this error. – user1818298 Oct 11 '16 at 14:41
  • You're right you aren't getting as far as basic auth (or other HTTP auth). The alias in the truststore doesn't matter; what matters is the hostname IN THE URL (which you redacted) and the hostname(s) in the cert. You have already made a local copy of the cert; look at it with `keytool -printcert` and use either the Owner CN (CommonName) or one of the names (or possibly addresses) from SubjectAlternativeName if present. Do NOT change domainname to address or vice versa; in many network contexts they are equivalent but not for HTTPS. – dave_thompson_085 Oct 11 '16 at 16:41
  • Thanks @dave_thompson_085. I'm trying to do the keytool command you presented now. I don't quite follow the last part. What exactly do I do with the Owner CN once I have it? – user1818298 Oct 11 '16 at 19:00
  • @dave_thompson_085 UPDATE: I was able to run that command. I don't see SubjectAlternativeName but I do see a CN. _Owner: EMAILADDRESS=email@emailcom (**redacted**), CN=owc, OU=Opsware Team, O=Opsware Inc., L=Sunnyvale, ST=CA, C=US_ Where would I use "owc"? – user1818298 Oct 11 '16 at 19:07
  • If server cert CN is `owc` (and no SAN), then with normal verifier logic the hostname part of your URL must be `owc`, e.g. `https://owc/some/app/?wsdl`. This means your platform must name-resolve `owc` to the server address; this depends on your OS and network environment, often DNS but sometimes other things like MDNS NIS LDAP etc. First try `telnet owc 443` if available or anything similar like `netcat` or on Unix `getent hosts owc`; if this correctly resolves you are OK. Else ask your network admin, or give details here (or maybe a new Q). Or go with the HostnameVerifier override. – dave_thompson_085 Oct 13 '16 at 02:13

1 Answers1

10

I generally don't recommend compiling absolute URLs. It makes builds unstable and introduces problems like the one you're suffering.

A better solution is to download and store related resources locally in the project and use catalog files to rewrite URLs.

I'll assume an absolute URL like http://www.my.org/wsdl/my.wsdl. Download resources from http://www.my.org and store them under src/main/resource/www.my.org.

Then write a src/main/resources/catalog.cat file like:

REWRITE_SYSTEM "http://www.my.org" "www.my.org"

Configure it in the plugin:

<configuration>
    <catalog>src/main/resources/catalog.cat</catalog>
    <schemaLanguage>WSDL</schemaLanguage>
    <schemas>
        <schema>
            <url>http://www.my.org/wsdl/my.wsdl</url>
        </schema>
    </schemas>
</configuration>

XJC will rewrite your http://www.my.org/wsdl/my.wsdl URL as src/main/resources/www.my.org/wsdl/my.wsdl.

There are a few caveats to this like you won't be able to mix relative and absolute URLs, but at the end this is much stable than relying on an external resource in the build. You really want builds to be stable and repeatable. Think of what happens if someone will update my.wsdl on the server.

Disclaimer: I'm the author of the maven-jaxb2-plugin.

lexicore
  • 42,748
  • 17
  • 132
  • 221