If you want to use WSS4J with generated stubs, it's often easiest to use a
client-side Axis configuration file (client-config.wsdd). You can just
put this file in the working directory you run the client from,
or full information about where Axis looks for it can be found at:
http://wiki.apache.org/old/AxisProjectPages/AxisClientWSDD).
There should be an example of this configuration file that enables message
signing in the samples/org/apache/ws/axis/samples/wssec/doall directory.
The sample is really old (and I'm not sure if it actually works), but I
think the configuration files in those directories might prove useful.
Hope this helps, below is some more information about the specifics of the
config file(s).
David
----------------------------------------------
A sample client-config.wsdd looks something like:
<?xml version="1.0" encoding="UTF-8"?>
<deployment>
<service name="SecHttp">
<requestFlow>
<handler name="DoSecuritySender"
type="java:org.apache.ws.axis.security.WSDoAllSender" >
<parameter name="action" value="Signature Encrypt"/>
<parameter name="user" value="16c73ab6-b892-458f-abf5-2f875f74882e"/>
<parameter name="passwordCallbackClass"
value="org.apache.ws.axis.samples.wssec.doall.PWCallback"/>
<parameter name="signaturePropFile" value="crypto.properties" />
<parameter name="signatureKeyIdentifier" value="DirectReference" />
<parameter name="encryptionKeyIdentifier" value="X509KeyIdentifier" />
</handler>
</requestFlow>
...
<responseFlow>
...
</responseFlow>
</service>
</deployment>
An axis client side handler is being configured for the SecHttp service.
The type="java:org.apache.ws.axis.security.WSDoAllSender" defines the name
of the class to be invoked. So every time a message gets sent
WSDoAllSender's invoke(MessageContext) method will get called (this is
just the way Axis handlers work). The rest of the parameters defined for
the <handler> in the configuration file get passed to WSDoAllSender and
get used to determine what should be done to the message.
The action parameter is especially important:
<parameter name="action" value="Signature Encrypt"/>
This tells WSS4J to sign the outgoing message first, then encrypt it. (The
order is important, which is why the response handler has the order
reversed; so that it decrypts first, then processes the signature.) What
keys should it use for the signature and encryption? This is what the rest
of the parameters are configuring.
The <parameter name="signaturePropFile" value="crypto.properties" />
specifies a file that contains information about the keystore to use. I
think the crypto.properties file is in the top-level src directory (not
the samples dir). If you take a look at it, it should look something like:
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypt
o.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=pkcs12
org.apache.ws.security.crypto.merlin.keystore.password=security
org.apache.ws.security.crypto.merlin.keystore.alias=16c73ab6-b892-458f-abf5-
2f875f74882e
org.apache.ws.security.crypto.merlin.alias.password=security
org.apache.ws.security.crypto.merlin.file=keys/x509.PFX.MSFT
This is the Java properties file format (just a list of
propertyname=value). Here's a quick explanation of the options:
- crypto.provider sets the Java cryptographic provider class to use (Sun's
Java documentation has more info on crypto providers, you can usually just
leave this setting as is).
- merlin.file indicates the path of a keystore file to load keys and
certificates from. This makes use of the Java keystore mechanism (again
more info can be had from Sun).
- keystore.type is used to determine how to read from the specified
keystore. PKCS12 indicates a PKCS12 packaged certificate and private key
(Microsoft calls this format PFX). Another often used keystore type is JKS
(Java keystore which is Java's natively supported format that can store
multiple keys and certificates in a single file).
- keystore.password sets the password used to protect the keystore you're
accessing
- keystore.alias and alias.password can be used to indicate the alias of a
key to read from the keystore and its associated password. Because of the
way client-config.wsdd is configured, however, these won't be used. In
fact I think these options may no longer even supported by WSS4J (to avoid
storing a plaintext password). So you'll have to use a callback class.
If you're familiar with the Java keytool program at all (distributed with
the J2SDK), you could run something like (all on one line):
keytool -list -keystore keys/x509.PFX.MSFT -storetype pkcs12
-storepass security
which would show you some information about what is stored in
keys/x509.PFX.MSFT. This is basically how WSS4J will use this
configuration information to access the keystore.
Stepping back to the client-config.wsdd file, we should next look at these
two parameters:
<parameter name="user" value="16c73ab6-b892-458f-abf5-2f875f74882e"/>
<parameter name="passwordCallbackClass"
value="org.apache.ws.axis.samples.wssec.doall.PWCallback"/>
This is where WSS4J gets the keystore alias and password to use (instead
of the crypto.properties file). Notice the value of the user parameter
above is the same as the keystore.alias set in the properties file (you
should also see this alias printed if you run keytool -list). For the
password for that alias, the PWCallback class will be invoked and it will
be passed a username (in this case 16c73ab6-b892-458f-abf5-2f875f74882e)
which it should lookup a password for. The password returned will be used
as the password to access the desired key in the keystore (the one with
alias 16c73ab6-b892-458f-abf5-2f875f74882e). If you actually look at
org.apache.ws.axis.samples.wssec.doall.PWCallback, you'll see that it
always returns the value 'security' regardless of the username (alias)
passed. A more sophisticated password callback class might ask the user
for his or her key password, or do some kind of lookup.
At any rate, with this set of options, WSS4J's WSDoAllSender can now
retrieve a key to use for message signing and encryption. The last two
parameters for the handler are:
<parameter name="signatureKeyIdentifier" value="DirectReference" />
<parameter name="encryptionKeyIdentifier" value="X509KeyIdentifier" />
The first tells WSS4J that when signing the message, it should include the
public key (certificate) by direct reference, so the certificate data will
actually be included in the security header rather than referencing a
certificate retrievable elsewhere. The encryptionKeyIdentifier indicates
that asymmetric encryption will be used (using the private key).
There actually is some (limited) documentation for the various WSDD
parameters that can be configured. The Javadocs for WSHandlerConstants and
WSConstants might prove helpful.
For example, if you wanted to use a username token instead of message
signing, you would simply change the handler action configured. The user
and passwordCallback parameters would still be used (for the username and
password to send).
So that's about it for configuring the client-side handler for outgoing
messages. There is a similar response handler configured that does
decryption, then processes the message signature (using WSDoAllReceiver).
Configuring similar handlers for the service is almost the same, take a
look at the sample server-config.wsdd file for details.
As a final note, you can also do all of this through code instead of with
the configuration files, although it probably involves a little more
effort.
------------------------------------------
[EMAIL PROTECTED] said:
> Thanks for your reply, Stefan. I saw that website before but I had some p=
> roblems with the examples. Take this one for example:
>
> Document envelope =3D ...
> WSSignEnvelope signer =3D new WSSignEnvelope();
> Crypto crypto =3D CryptoFactory.getInstance("crypto.properties");
> Vector parts =3D new Vector();
> WSEncryptionPart part =3D new WSEncryptionPart(soapConstants.getBodyQName=
> ().getLocalPart(),
> soapConstants.getEnvelopeURI=
> (),
> "Content");
> parts.add(part);
> signer.setParts(parts); // this is optional since the body is signed by d=
> efault
> envelope =3D signer.build(envelope, crypto);
>
>
> What do I have to enter after "Document envelope =3D "? And I can't find=
> "soapConstants" anywhere either. Plus, I always make Web services as fol=
> low: first make the WSDL, then generate Java classes from it, then make a=
> call like this:
>
> PingServiceLocator service =3D new PingServiceLocator();
> PingPort port =3D service.getPing1();
>
> It looks like they are writing the whole SOAP message in the example at h=
> ttp://www.mail-archive.com/[email protected]/msg00022.html
> Can't I do it like I do as above (create the service, create the port fro=
> m the service)?
>
>
> Thanks for your reply again
>
>
>