views:

1093

answers:

1

Hi all,

I'm working on a small-ish multi-module project in Maven. We've separated the UI from the database layer using Web Services, and thanks to the jaxws-maven-plugin, the creation of the WSDL and WS client are more or less handled for us. (The plugin is essentially a wrapper around wsgen and wsimport.) So far so good.

The problem comes when I try to layer WSIT security into the picture. NetBeans allows me to generate the security metadata easily, but wsimport seems completely incapable of dealing with anything beyond a Basic-auth level of security.

Here's our current, insecure way of calling wsimport during a Maven build:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>jaxws-maven-plugin</artifactId>
    <version>1.10</version>
    <executions>
        <execution>
            <goals>
                <goal>wsimport</goal>
            </goals>
            <configuration>
                <wsdlUrls>
                    <wsdlUrl>${basedir}/../WebService/target/jaxws/wsgen/wsdl/WebService.wsdl</wsdlUrl>
                </wsdlUrls>
                <packageName>com.yourcompany.appname.ws.client</packageName>
                <sourceDestDir>${basedir}/src/main/java</sourceDestDir>
                <destDir>${basedir}/target/jaxws</destDir>
            </configuration>
        </execution>
    </executions>
</plugin>

I have tried playing around with xauthFile, xadditionalHeaders, passing javax.xml.ws.security.auth.username and password through args. I have also tried using wsimport from the command line to point to the Tomcat-generated WSDL, which has the additional security info. Nothing, however, seems to change the composition of the wsimport-generated files at all.

So I guess my question here is, to get a WSIT-compliant client, am I stuck abandoning Maven and the jaxws plugin altogether? Is there a way to get a WSIT client to auto-generate? Or will I need to generate the client by hand?

Let me know if you need any additional info beyond what I've written here. I'm deploying to Tomcat, although that doesn't seem to be an issue, as Maven seems happy to pull Metro into the deployed WAR file.

Thanks in advance!

EDIT: After a lot of playing around with WSIT, here's what worked for me.

For starters, use Netbeans to generate a WSIT client. Test it to make sure it works, and then move the WSIT configuration files (wsit-client.xml and [your web service name].xml) to the META-INF directory of the WS client project.

The relevant addition to your project, from a security standpoint, is the tag in the web service xml:

<wsp:Policy wsu:Id="WebPortBindingPolicy">
    <wsp:ExactlyOne>
        <wsp:All>
            <sc:CallbackHandlerConfiguration wspp:visibility="private">
                <sc:CallbackHandler default="wsitUser" name="usernameHandler"/>
                <sc:CallbackHandler default="changeit" name="passwordHandler"/>
            </sc:CallbackHandlerConfiguration>
            <sc:TrustStore wspp:visibility="private" location="C:\Apps\apache-tomcat-6.0.24\certs\client-truststore.jks" type="JKS" storepass="changeit" peeralias="xws-security-server"/>
        </wsp:All>
    </wsp:ExactlyOne>
</wsp:Policy>

Obviously, there are some hard-coded dependencies in here that we'll need to manage during our build. The user, password, location of the truststore, and the peeralias are all development defaults, and will change as the system moves from dev into testing and production. We're playing around with a few different strategies for managing this, but we'll probably end up setting environment variables in Hudson for build-out to each environment.

Fiddle with the configuration of Maven's jaxws plugin a little. We generate the WSDL as part of the build, so we don't need to reference it locally. Here is the plugin tag for the wsimport command in our WS client target:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>jaxws-maven-plugin</artifactId>
    <version>1.12</version>
    <executions>
        <execution>
            <goals>
                <goal>wsimport</goal>
            </goals>
            <configuration>
                <wsdlUrls>
                    <wsdlUrl>${basedir}/../WebService/target/jaxws/wsgen/wsdl/WebService.wsdl</wsdlUrl>
                </wsdlUrls>
                <staleFile>${project.build.directory}/jaxws/stale/WebService.stale</staleFile>
                <packageName>com.yourcompany.appname.ws.client</packageName>
                <sourceDestDir>${basedir}/src/main/java</sourceDestDir>
                <destDir>${basedir}/target/jaxws</destDir>
            </configuration>
            <id>wsimport-generate-WebService</id>
            <phase>generate-sources</phase>
        </execution>
    </executions>
    <dependencies>
        <dependency>
            <groupId>javax.xml</groupId>
            <artifactId>webservices-api</artifactId>
            <version>2.0-b30</version>
        </dependency>
    </dependencies>
    <configuration>
        <sourceDestDir>${project.build.directory}/generated-sources/jaxws-wsimport</sourceDestDir>
        <xnocompile>true</xnocompile>
        <verbose>true</verbose>
        <extension>true</extension>
    </configuration>
</plugin>

And finally, of course, make sure that all your projects that will need to call web services have the Metro dependency properly set up.

+2  A: 

Aren't you just supposed to provide the Client-Side WSIT Configuration Files for the client? What do you expect from wsimport exactly?

Edit: As implied, the WSIT document describes two client-side configuration files: wsit-client.xml and {wsdl file name}.xml and:

When running the client, these files will need to be in the classpath, either at the classpath root (i.e., build/classes) or in a META-INF directory under the classpath root.

Transposed to a Maven project, the natural location for these files would be src/main/resources or src/main/resources/META-INF folder. Personally, I tend to prefer putting them in META-INF.

Pascal Thivent
The "just" part of that is the trick. I've done a lot of work on this today, and following the WSIT tutorial I was able to get NetBeans to create a secure WS Client. I still haven't been able to get my Maven project to play happily with the configuration, but I'm close. This is my first secure Web Service, so I'm learning as I go along. I'll probably submit my own answer as a mini-tutorial on how I did it, so others can avoid some of the pain I've gone through. Thanks!
rtperson
@rtperson I'm not saying WSIT is trivial but I still don't get what you're expecting to happen during wsimport. AFAIK, providing client-side WSIT configuration files doesn't impact the generation of client artifacts.
Pascal Thivent
Pascal, now that I've seen how the pieces fit together, I know that wsimport won't do anything differently than it's doing now, so I've managed to move past that. But I haven't yet been able to create a secure WSIT client through Maven. I'm home now, and I don't have the code in front of me, but the client configuration files are just the two that live in META-INF, correct? The wsit_client configuration and the web service descriptor? (This is my first time implementing WSIT, if you can't tell. Forgive the huge gaps in my knowledge.)
rtperson
@rtperson I've updated my answer to cover this. And TBH, I can't say I found WSIT very intuitive/friendly so I will certainly not blame you :)
Pascal Thivent
True that. I like WSIT better than the hand-coded security handler classes in the sample code from the old JWSDP, and the QOS guarantees between JWS and .NET is nice. But honestly, if NetBeans didn't allow for automatic generation of the configurations, I'm not sure how I would have been able to figure it out how to do it by hand.
rtperson
@rtperson Sure, WSIT is nice... for a machine (but as you said, NetBeans has good support for it, I used it too when I had to deal with WSIT).
Pascal Thivent