WSS4J Documentation is here!
Due to the increasing demand, I attached a work in progress. index.html is the main file (please revise my list of features), api.html is an overview of the WSS4J Java API, axis.html is a detailed step by step tutorial on creating a secure service and a client using WSS4J/Axis.
So far I only did Username Token in the tutorial. Please review/edit so we can maybe publish it on the web site soon (I'm not sure how and where this should be checked in so it shows up on the public web site).
I used package.html as a reference for details on Axis handlers assuming that it will be eventually available and accessible by users (hopefully via a convenient link), so I only listed steps with samples without much explanations as in package.html.
Rami Jaamour Software Engineer Web Services Solutions Parasoft Corporation
"We Make Software Work"
Johan Danforth wrote:
Werner,Title: Apache WSS4J API Overview
Yes, I've looked at that file and I've browsed through most of the
source code that comes with WSS4J without much success I'm afraid. I could
give it another go I guess, but I don't want to spend days to get into it.
Can someone just explain the steps in a pseudo-way maybe? BTW. If there are problems getting WSS4J working with ASP.NET + WSE
2.0, maybe I shouldn't go down that route right now anyway... I need to send
a binary token from java soap (axis) clients to web services built with
ASP.NET, so maybe I should just use normal soap headers for now.
/Johan
-----Original Message-----
From: Werner Dittmann [mailto:[EMAIL PROTECTED] Sent: den 7 januari 2005 13:13
To: Johan Danforth
Cc: [EMAIL PROTECTED]; 'Ted Toth'; fx-dev@ws.apache.org
Subject: Re: tutorials or walkthroughs?
Johan,
sorry for the lack of documentation so far. I'm sure you already
looked
at the "package.html" file in "src/org/apache/ws/axis/security". In
addition
you may have a look at the interop examples.
If you have a complete checkout of wss4j the pls go to the "specs" directory.
This dir contains the "ping.wsdl" file that is used to build the
interop scenarios
as defined by OASIS. The resulting *.java classes (from WSDL2JAVA)
are in
"build/work/org/apache/ws/axis/oasis/ping". The other parts are
located in
"interop/org/apache/ws/axis/oasis/*".
Hope this gets you a step further.
Regards,
Werner
Johan Danforth schrieb:
> Ted, Dims, thanks for the answers.
> First, the need for a basic tutorial is still needed. I still
don't
>understand how to use WSS4J, and I know there are others out there
with the
>same question. I'm in contact with lots of Swedish developers and
solution
>architects that are really interested in WSS4J, but we all need some
help to
>get into it. So please, a simple step-by-step thingy about how to
create a
>console app soap client that uses AXIS WSDL2JAVA stubs, that would
be
>perfect! > I would love to help out with a patch, but again, I need to
get into
>WSS4J first :) Tim, it sounds like you've know lots about this,
can't you
>write down a few simple steps? (Promise to buy you a pint of beer,
coke or
>whatever if we meet ;)
> /Johan
> -----Original Message-----
>From: Davanum Srinivas [mailto:[EMAIL PROTECTED] >Sent: den 6 januari 2005 16:07
>To: Ted Toth
>Cc: Johan Danforth; fx-dev@ws.apache.org
>Subject: Re: tutorials or walkthroughs?
> ><snip>
>
> >
Apache WSS4J API Overview
Contents
- API Overview
- WSSecurityEngine
- WSBaseMessage
- WSSignEnvelope (extends WSBaseMessage)
- WSAddTimestamp (extends WSBaseMessage)
- WSEncryptBody (extends WSBaseMessage)
- WSAddUsernameToken (extends WSBaseMessage)
- WSSAddSAMLToken (extends WSBaseMessage)
- Examples
- Sign the SOAP Body
- Encrypt the SOAP Body
- Process WSS Header and Check the Results
API Overview
WSS4J can be used as a library to provide an API for WS-Security
processing. In this case WSS4J does not need to be used with Axis, or
even be a part of a deployed web application. The WSS4J API can be
invoked directly to create WS-Security headers or process them given a
SOAP Envelope DOM Document.
Following is an overview of the main classes and methods for the
WSS4J API. Please refer to the java docs for the complete API
documentation.
org.apache.ws.security.WSSecurityEngine
Action |
Method |
|
Get an instance of security engine |
public static org.apache.ws.security.WSSecurityEngine getInstance() |
|
Description |
Get
a singleton instance of security engine
class. If you need to get an instance configured for an older spec
(different namespaces) then use the other method which takes
org.apache.ws.security.WSSConfig |
|
Parameters |
||
Returns |
org.apache.ws.security.WSSecurityEngine |
Processes
WS-Security Headers in a SOAP Envelope |
Action |
Method |
|
Verify WSS Headers |
java.util.Vector processSecurityHeader( |
|
Description |
Takes
a SOAP Envelope as a W3C Document and verifies the WSS Headers.
This
includes Username Token processing, Signature verification, decryption
and timestamp verification. In the case of encrypted elements,
decryption is performed live on the passed document, i.e., it is
transformed into the decrypted format. |
|
Parameters |
doc |
the SOAP Envelope as W3C DOM Document |
actor | the
engine works on behalf of this actor. Refer to the SOAP specification
about actor or role, this may be null. |
|
cb |
a callback hander to the caller
to resolve passwords during encryption and UsernameToken handling, this
may be null. |
|
crypto |
the
object that implements the access to the keystore and the handling of
certificates. A default implementation is included:
org.apache.ws.security.components.crypto.Merlin |
|
Returns |
java.util.Vector |
Vector of
org.apache.ws.security.WSSecurityEngineResult, this has the information
resulting from the processing, such as the principal, SAML token, etc. |
org.apache.ws.security.message.WSBaseMessage
Action |
Method |
|
Set the Signature/Encryption
parts |
public void setParts(java.util.Vector parts) |
|
Description |
Takes
a vector of org.apache.ws.security.WSEncryptionPart. |
|
Parameters |
doc |
the SOAP Envelope as W3C DOM Document |
crypto |
the
object that implements the access to the keystore and the handling of
certificates. A default implementation is included:
org.apache.ws.security.components.crypto.Merlin |
|
Returns |
org.w3c.dom.Document |
the
SOAP Envelope Signed. The signed elements depend on the signature parts
that are specified by the WSBaseMessage.setParts(java.util.Vector
parts) method |
org.apache.ws.security.message.WSSignEnvelope
(extends WSBaseMessage)
Action |
Method |
|
Signs a SOAP Envelope |
public org.w3c.dom.Document build( |
|
Description |
Takes a SOAP Envelope as a W3C Document and adds WSS Signature header to it. The signed elements depend on the signature parts that are specified by the WSBaseMessage.setParts(java.util.Vector parts) method. By default, SOAP Body is signed | |
Parameters |
doc |
the SOAP Envelope as W3C DOM Document |
crypto |
the
object that implements the access to the keystore and the handling of
certificates. A default implementation is included:
org.apache.ws.security.components.crypto.Merlin |
|
Returns |
org.w3c.dom.Document |
the
SOAP Envelope signed. |
org.apache.ws.security.message.WSAddTimestamp
(extends WSBaseMessage)
Action |
Method |
|
Add a Timestamp Token to a SOAP Envelope |
public org.w3c.dom.Document build( |
|
Description |
Takes
a SOAP Envelope as a W3C Document and adds a Timestamp header to
it. Please refer to the WS specification 1.0. chapter 10 / appendix A.2
|
|
Parameters |
doc |
the SOAP Envelope as W3C DOM Document |
ttl |
(time
to live) This is the time difference in seconds between the Created
and the Expires in Timestamp , set to zero
if Expires should not be added. |
|
Returns |
org.w3c.dom.Document |
the
SOAP Envelope with the Timestamp added |
org.apache.ws.security.message.WSEncryptBody
(extends WSBaseMessage)
Action |
Method |
|
Encrypt a SOAP Envelope |
public org.w3c.dom.Document build( |
|
Description |
Takes a SOAP Envelope as a W3C Document and adds WSS Encryption header to it. Unlike what the class name might imply, this can be used to encrypt elements in the SOAP Header, such as Username Tokens or other arbitrary elements. The encrypted elements depend on the signature parts that are specified by the WSBaseMessage.setParts(java.util.Vector parts) method. By default, SOAP Body is encrypted | |
Parameters |
doc |
the SOAP Envelope as W3C DOM Document |
crypto |
the
object that implements the access to the keystore and the handling of
certificates. A default implementation is included:
org.apache.ws.security.components.crypto.Merlin |
|
Returns |
org.w3c.dom.Document |
the
SOAP Envelope encrypted. |
org.apache.ws.security.message.WSAddUsernameToken
(extends WSBaseMessage)
Action |
Method |
|
Add a Username Token to a
SOAP Envelope |
public org.w3c.dom.Document build( |
|
Description |
Takes a SOAP Envelope as a W3C Document and adds a Username Token header to it. Use setPasswordType(java.lang.String pwType) to choose between plain text passwords and digested ones. | |
Parameters |
doc |
the SOAP Envelope as W3C DOM Document |
username |
the
username to use |
|
password |
the password to use (a plain
text string) |
|
Returns |
org.w3c.dom.Document |
the
SOAP Envelope with the username token header added |
org.apache.ws.security.message.WSSAddSAMLToken
(extends WSBaseMessage)
Action |
Method |
|
Add a SAML Token to a SOAP Envelope |
public org.w3c.dom.Document build( |
|
Description |
Takes
a SOAP Envelope as a W3C Document and adds a SAML Assertion Token
header to
it. Please refer to the OpenSAML documentation on how to construct SAML
assertions. |
|
Parameters |
doc |
the SOAP Envelope as W3C DOM Document |
assertion |
the
SAML assertion to add |
|
Returns |
org.w3c.dom.Document |
the
SOAP Envelope with the SAML assertion header added |
Examples
Sign the SOAP Body
Document envelope = ...WSSignEnvelope signer = new WSSignEnvelope();
Crypto crypto = CryptoFactory.getInstance("crypto.properties");
Vector parts = new Vector();
WSEncryptionPart part = new WSEncryptionPart(soapConstants.getBodyQName().getLocalPart(),
soapConstants.getEnvelopeURI(),
"Content");
parts.add(part);
signer.setParts(parts); // this is optional since the body is signed by default
envelope = signer.build(envelope, crypto);
Encrypt the SOAP Body
Document envelope = ...WSEncryptBody encryptor = new WSEncryptBody();
Crypto crypto = CryptoFactory.getInstance("crypto.properties");
Vector parts = new Vector();
WSEncryptionPart part = new WSEncryptionPart(soapConstants.getBodyQName().getLocalPart(),
soapConstants.getEnvelopeURI(),
"Content");
parts.add(part);
encryptor.setParts(parts); // this is optional since the body is encrypted by default
envelope = encryptor.build(envelope, crypto);
Process WSS Header and Check the Results
Document envelope = ...WSSecurityEngine secEngine = WSSecurityEngine.getInstance();
Crypto crypto = CryptoFactory.getInstance("crypto.properties");
//
javax.security.auth.callback.CallbackHandler
// please refer to the tests for examples of callback handlers
CallbackHandler cb = new MyCallbackHandler();
Vector results = secEngine.processSecurityHeader(envelope, null,
cb
,
crypto);for (int i = 0; i < results.size(); i++) {
WSHandlerResult hResult = (WSHandlerResult)results.get(i);
String actor = hResult.getActor();
Vector hResults = hResult.getResults();
for (int j = 0; j < hResults.size(); j++) {
WSSecurityEngineResult eResult = (WSSecurityEngineResult)hResults.get(j);
// Note: an encryption action does not have an associated principal
// only Signature and UsernameToken actions return a principal
if (eResult.getAction() != WSConstants.ENCR) {
System.out.println(eResult.getPrincipal().getName());
}
}
}
Title: Axis Deployment Tutorial
Apache WSS4J
Axis Deployment Tutorial
Contents
- Introduction
- Prerequisties
- Steps
- Username Token
Introduction
Prerequisties
Steps
Installing WSS4J
- Download the WSS4J binaries or build it from sources
- Copy the contents of the WSS4J lib directory to your Axis WEB-INF/lib directory. Many jar files will already exist. Most of them will already exist there but you can just overwrite them all.
- You may need to restart Tomcat unless you have automatic deployment/class loading turned on. Check the Axis Happiness Page (typically at http://localhost:8080/axis), make sure that the XML Security (xmlsec.jar) is listed under the "Optional Components" section.
Creating the Service
- This tutorial will secure the StockQuoteService which ships with Axis. Unless you have one already, create a deployment descriptor (deploy.wsdd) file with the following contents:
- deploy the service (using AxisAdmin):
<deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<service name="stock-wss-01" provider="java:RPC" style="document" use="literal">
<parameter name="className" value="samples.stock.StockQuoteService"/>
<parameter name="allowedMethods" value="getQuote"/>
<parameter name="scope" value="application"/>
</service>
</deployment>
-
java
org.apache.axis.client.AdminClient
-lhttp://localhost:8080/axis/services/AdminService deploy.wsdd
Creating the Client
- Use WSDL2Java to generate the client service bindings:
java org.apache.axis.wsdl.WSDL2Java -o . -Nhttp://fox:8080/axis/services/stock-wss-01 samples.stock.client http://fox:8080/axis/services/stock-wss-01?wsdl
A bunch of java classes will be created under samples/stock/client, including the StockQuoteServiceServiceLocator.
- Write a simple java client that uses the generated service
locator. For example:
package samples.stock.client;
import java.rmi.RemoteException;
import javax.xml.rpc.ServiceException;
public class StockServiceClient {
public StockServiceClient() {
}
public static void main(String[] args) throws ServiceException, RemoteException {
if (args.length == 0) {
System.out.println("Usage:\njava StockServiceClient [symbol]");
return;
}
StockQuoteServiceService locator = new StockQuoteServiceServiceLocator();
StockQuoteService service = locator.getStockWss01();
float quote = service.getQuote(args[0]);
System.out.println("stock quote service returned " + args[0] + ": " + quote);
}
}
- run the client:
java samples.stock.client.StockServiceClient IBM
If all went well, you should get the result:
stock quote service returned IBM: 95.68
Username Token
Configuring the Service
- Modify the deployment descriptor you created above to look like
this:
<deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<service name="stock-wss-01" provider="java:RPC" style="document" use="literal">
<requestFlow>
<handler type="java:org.apache.ws.axis.security.WSDoAllReceiver">
<parameter name="passwordCallbackClass" value="PWCallback"/>
<parameter name="action" value="UsernameToken"/>
</handler>
</requestFlow>
<parameter name="className" value="samples.stock.StockQuoteService"/>
<parameter name="allowedMethods" value="getQuote"/>
<parameter name="scope" value="application"/>
</service>
</deployment>
WSDoAllReceiver is an Axis handler that can be located in wss4j.jar. This is the standard way to deploy an Axis handler. For more details please refer to the Axis handler for WSS4J documentation.
- Create a class named PWCallback.java and compile it into your
Axis WEB-INF/classes directory. In this example I used the default
package for simplicity, but you might need to use the fully qualified
class name (be consistent
with the deployment descriptor).
The following code snippet shows a simple password callback class:
import java.io.IOException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.ws.security.WSPasswordCallback;
public class PWCallback implements CallbackHandler {
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
if (callbacks[i] instanceof WSPasswordCallback) {
WSPasswordCallback pc = (WSPasswordCallback)callbacks[i];
// set the password given a username
if ("wss4j".equals(pc.getIdentifer())) {
pc.setPassword("security");
}
} else {
throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
}
}
}
}
- Redeploy the service. Your service should now be expecting a WSS
Username Token in in the incoming requests, and clients should send the
username "wss4j" and password "security" to get through.
Configuring the Client
- run the client we created again:
java samples.stock.client.StockServiceClient IBM
You should now get an error:
Exception in thread "main" AxisFault
faultCode: {http://schemas.xmlsoap.org/soap/envelope/}Server.generalException
faultSubcode:
faultString: WSDoAllReceiver: Request does not contain required Security header
This is because your client is not configured to send a Username Token yet, so the service is rejecting the request.
- Create a deployment descriptor file (client_deploy.wsdd) for the
client:
<deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<transport name="http" pivot="java:org.apache.axis.transport.http.HTTPSender"/>
<globalConfiguration >
<requestFlow >
<handler type="java:org.apache.ws.axis.security.WSDoAllSender" >
<parameter name="action" value="UsernameToken"/>
<parameter name="user" value="wss4j"/>
<parameter name="passwordCallbackClass" value="samples.stock.client.PWCallback"/>
<parameter name="passwordType" value="PasswordDigest"/>
</handler>
</requestFlow >
</globalConfiguration >
</deployment>
- Create the samples.stock.client.PWCallback
class:
package samples.stock.client;
import java.io.IOException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.ws.security.WSPasswordCallback;
/**
* PWCallback for the Client
*/
public class PWCallback implements CallbackHandler {
/**
* @see javax.security.auth.callback.CallbackHandler#handle(javax.security.auth.callback.Callback[])
*/
public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
if (callbacks[i] instanceof WSPasswordCallback) {
WSPasswordCallback pc = (WSPasswordCallback)callbacks[i];
// set the password given a username
if ("wss4j".equals(pc.getIdentifer())) {
pc.setPassword("security");
}
} else {
throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
}
}
}
}
- Define the system property axis.ClientConfigFile for your client:
java -Daxis.ClientConfigFile=client_deploy.wsdd -classpath $AXISCLASSPATH samples.stock.client.StockServiceClient
Make sure that your classpath includes the jar files under WEB-INF/lib.
Another way to do this is to specify the wsdd file in your StockServiceClient to the service locator programmatically:
...
import org.apache.axis.EngineConfiguration;
import org.apache.axis.configuration.FileProvider;
...
EngineConfiguration config = new FileProvider("client_deploy.wsdd");
StockQuoteServiceService locator = new StockQuoteServiceServiceLocator(config);
...
- Run the client, you should get no errors:
stock quote service returned IBM: 95.7
Your client is now sending a Username Token in the wsse request header with the username "wss4j" (see client_deploy.wsdd) and password "security" (see the PWCallback implementation).
Another way to do this is to have the client application set the username and CallbackHandler implementation programmatically instead of client_deploy.wsdd:
...
import org.apache.axis.client.Stub;
...
Remote remote = locator.getPort(StockQuoteService.class);
Stub axisPort = (Stub)remote;
axisPort._setProperty(UsernameToken.PASSWORD_TYPE, WSConstants.PASSWORD_DIGEST);
axisPort._setProperty(WSHandlerConstants.USER, "wss4j");
axisPort._setProperty(WSHandlerConstants.PW_CALLBACK_REF, pwCallback);
where "pwCallback" is a reference to a PWCallback implementation. See the Axis handler for WSS4J documentation for more details on this.
- Try modifying your client's PWCallback to return the wrong password, or send the wrong username. The service should reject your requests.
Title: WSS4J Documentation
Apache WSS4J Documentation
Contents
- What is WSS4J?
- WS-Security Features
- WSS4J Use Cases
- WSS4J API
- WSS4J on Axis
What is WSS4J?
Apache WSS4J is an implementation of the
OASIS Web Services Security (WS-Security) from OASIS
Web Services Security TC.
WSS4J implements
- OASIS Web Serives Security: SOAP Message Security 1.0 Standard 200401, March 2004
- Username Token profile V1.0
- X.509 Token Profile V1.0
WS-Security Features
WSS4J can generate and process the
following SOAP Bindings:
- XML Security
- XML Signature
- XML Encryption
- Tokens
- Username Tokens
- Timestamps
- SAML Tokens
WSS4J Use Cases
WSS4J API
Please refer to the API
Overview
for details.
WSS4J on Axis
Please refer to the the Axis
Deployment Tutorial for details.