|
|||||||||||
| PREV PACKAGE NEXT PACKAGE | FRAMES NO FRAMES | ||||||||||
See:
Description
| Class Summary | |
| WSDoAllReceiver | |
| WSDoAllSender | |
Provides classes and interfaces that implement WSS4J Axis handlers. These handler process SOAP requests according to the OASIS Web Service Security (WSS) specifications.
The WSS4J Axis handlersWSDoAllSender and WSDoAllReceiver
control the creation and consumption of secure SOAP requests.
The handlers work behind the scenes and are usually transparent to Web Service
(WS) applications. The Axis deployment descriptor files (*.wsdd) may contain all
necessary information to control the security processing.
A WS application may also set properties to control the handlers
and provide default values. If the deployment descriptor sets the same
property (parameter) then the deployment descriptor overwrites the application
defined property. Thus, deployment settings overwrite application settings
to fulfill site specific requirements.
UsernameTokenWSHandlerConstants,
WSDoAllSender, and
WSDoAllReceiver
provide additional and detailed documentation.
UsernameToken
<!-- define the service, use the WSDoAllSender security handler in request flow -->
<service name="Ping1">
<requestFlow>
<handler type="java:org.apache.ws.axis.security.WSDoAllSender" >
<parameter name="action" value="UsernameToken"/>
<parameter name="user" value="werner"/>
<parameter name="passwordType" value="PasswordText" />
<parameter name="passwordCallbackClass"
value="org.apache.ws.axis.oasis.PWCallback1"/>
</handler>
</requestFlow>
</service>
This is the standard way to deploy an Axis handler. Axis parses the deployment
descriptor and provides the parameters and their value to the handler. Each
service can have its own request and response flow definition, which provides
a very flexible set-up of the security parameters.
The above setup inserts the most simple security structure into a SOAP request:
the simple UsernameToken. This token includes a username and the
according password. Both fields are sent in cleartext, thus it provides no
real security.
The parameters and their meanings are:
action defines the security action. The value
UsernameToken directs the handler to insert this token into
the SOAP request.
user specifies the username to include in the token.
passwordType is a pecific parameter for the
UsernameToken action and defines the encoding of the passowrd.
PasswordText specifies to send the password in
plain text, PasswordDigest specifies to send the
password in digest mode (refer to WSS UsernameToken Profile)
passwordCallbackClass contains the name of a class that
implements a method to get the user's password. Please refer to the
detailed documentation in
WSHandlerConstants.PW_CALLBACK_CLASS.
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header>
<wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/07/secext"
soapenv:mustUnderstand="true">
<wsse:UsernameToken>
<wsse:Username>werner</wsse:Username>
<wsse:Password Type="wsse:PasswordText">security</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<Ping xmlns="http://xmlsoap.org/Ping">
<text>Scenario 1 text</text>
<ticket xmlns:ns1="http://xmlsoap.org/Ping"
xsi:type="ns1:ticketType">scenario1</ticket>
</Ping>
</soapenv:Body>
</soapenv:Envelope>
This is a pretty print of the real SOAP message.
UsernameToken but not the password. In general it is not a
good idea to store sensitive information like a password in cleartext. To
get the password the WSS4J Axis handler uses a password callback
technique similar to the JAAS mechansim. The parameter
passwordCallbackClass contains the classname of the callback
class. This class must implement the
CallbackHandler
interface. The WSS4J Axis handler gets this class,
instantiates it, and calls the handle method when it
needs a password. Refer also to the
parameter documentation.
The following code snippet shows a simple password callback class:
package org.apache.ws.axis.oasis;
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 {
private static final byte[] key = {
(byte)0x31, (byte)0xfd, (byte)0xcb, (byte)0xda,
(byte)0xfb, (byte)0xcd, (byte)0x6b, (byte)0xa8,
(byte)0xe6, (byte)0x19, (byte)0xa7, (byte)0xbf,
(byte)0x51, (byte)0xf7, (byte)0xc7, (byte)0x3e,
(byte)0x80, (byte)0xae, (byte)0x98, (byte)0x51,
(byte)0xc8, (byte)0x51, (byte)0x34, (byte)0x04,
};
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];
/*
* here call a function/method to lookup the password for
* the given identifier (e.g. a user name or keystore alias)
* e.g.: pc.setPassword(passStore.getPassword(pc.getIdentfifier))
* for testing we supply a fixed name/fixed key here.
*/
if (pc.getUsage() == WSPasswordCallback.KEY_NAME) {
pc.setKey(key);
}
else {
pc.setPassword("security");
}
} else {
throw new UnsupportedCallbackException(
callbacks[i], "Unrecognized Callback");
}
}
}
}
The Java callback handler
documentation provides a detailed description of the interface and exceptions.
The WSS4J library uses a specific class to get the required password or key
informations. The WSSPasswordCallback class implements the
Callback interface according to the
JAAS. Depending on it usage this class either carries the required password
as a Java String or it carries the required key information
as a Java byte[] array. Refer to
WSPasswordCallback that contains a
detailed description of the usage codes.
The WSS4J Axis handler or the WSS4J modules set the usage code before
they call handle method.
UsernameTokensetProperty method to support this feature.
The following code snippet shows an example how to use the dynamic setting
of parameters and their values:
... Service service = new Service(); Call call = (Call) service.createCall(); ... call.setProperty(UsernameToken.PASSWORD_TYPE, WSConstants.PASSWORD_TEXT); call.setProperty(WSHandlerConstants.USER, "werner"); ...Use this way if your application dynamically creates a
call
object. If your application uses stubs generated by Axis' WSDL2Java
tool, the application uses the following functions:
...
PingServiceLocator service = new PingServiceLocator();
...
PingPort port = (PingPort) service.getPing1();
port._setProperty(UsernameToken.PASSWORD_TYPE, WSConstants.PASSWORD_TEXT);
port._setProperty(WSHandlerConstants.USER, "werner");
...
Please note that _setProperty is a Axis specific call.
setProperty() methods. Only applications (and Axis handlers that
preceed the WSS4J Axis handlers in a handler chain) can use this feature.
For example:
public class Scenario1 implements CallbackHandler {
public static void main(String args[]) {
...
PingServiceLocator service = new PingServiceLocator();
...
PingPort port = (PingPort) service.getPing1();
((org.apache.axis.client.Stub)port)._setProperty(UsernameToken.PASSWORD_TYPE, WSConstants.PASSWORD_TEXT);
((org.apache.axis.client.Stub)port._setProperty(WSHandlerConstants.USER, "werner");
((org.apache.axis.client.Stub)port._setProperty(WSHandlerConstants.PW_CALLBACK_REF, this);
...
}
public void handle(Callback[] callbacks) {
...
}
}
WSDoAllReceiver handlerWSDoAllSender
a deployment descriptor for the receiving handler exists. For the above
example the deployment descriptor look like:
<requestFlow>
<handler type="java:org.apache.ws.axis.security.WSDoAllReceiver">
<parameter name="passwordCallbackClass"
value="org.apache.ws.axis.oasis.PWCallback"/>
<parameter name="action" value="UsernameToken"/>
</handler>
</requestFlow>
The receiving WSS4J Axis handler checks if the SOAP request matches the defined
actions.
UsernameToken and EncryptionUsernameToken, use PasswordText
to set the password. In addition add a timestamp and a nonce into
the UsernameTokenUsernameToken to protect the information.
<requestFlow>
<handler type="java:org.apache.ws.axis.security.WSDoAllSender" >
<parameter name="action" value="UsernameToken Encrypt"/>
<parameter name="user" value="werner"/>
<parameter name="passwordCallbackClass"
value="org.apache.ws.axis.oasis.PWCallback"/>
<parameter name="passwordType" value="PasswordText" />
<parameter name="addUTElement" value="Nonce Created" />
<parameter name="encryptionPropFile" value="crypto.properties" />
<parameter name="encryptionKeyIdentifier" value="X509KeyIdentifier" />
<parameter name="encryptionUser"
value="16c73ab6-b892-458f-abf5-2f875f74882e" />
<parameter name="encryptionParts"
value="{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}UsernameToken" />
</handler>
</requestFlow>
This descriptor contains some new parameters to control the UsernameToken
element and its encryption. The new parameters and their meaning are:
addUTElement - controls if the handler shall insert elements
into the UsernameToken. The value is a blank separated list of
element names to include. Only Nonce and Created are
supported.encryptionPropFile - the name of a crypto property file. This
file contains parameters and property that control the encryption. Please refer
to the
detailed description of the cyrpto property file.encryptionKeyIdentifier - specifies the format in which the
handler inserts the encryption key into the SOAP request. Please refer
to the
detailed description.encryptionUser - the name or identifier of the user who owns
the public key to encrypt the data. Usually this is the name or alias name
of the owner's certificate in a keystore.encryptionParts - controls which part or parts the handler
of the SOAP shall encrypt. If this parameter is not defined, WSS4J encrypts
the whole SOAP Body in Content mode. The value of the
parameter in this example specifies to encrypt the element
UsernameToken, contained in the namespace
http://schemas.xmlsoap.org/ws/2002/07/secext. The encryption
module uses the Element mode to encrypt the element data.
Please refer to the
detailed description.
<requestFlow>
<handler type="java:org.apache.ws.axis.security.WSDoAllReceiver">
<parameter name="passwordCallbackClass"
value="org.apache.ws.axis.oasis.PWCallback"/>
<parameter name="action" value="UsernameToken Encrypt"/>
<parameter name="decryptionPropFile" value="crypto.properties" />
</handler>
</requestFlow>
The only new parameter here is the decryptionPropFile. This
parameter defines the crypto property file at the receiver side. The value
of the action parameter matches the according value at the
sender side. The WSS4J Axis receiver checks if the SOAP request contains
the required security data.
<requestFlow>
<handler type="java:org.apache.ws.axis.security.WSDoAllSender" >
<parameter name="user" value="16c73ab6-b892-458f-abf5-2f875f74882e"/>
<parameter name="passwordCallbackClass"
value="org.apache.ws.axis.oasis.PWCallback"/>
<parameter name="action" value="Signature Encrypt"/>
<parameter name="signaturePropFile" value="crypto.properties" />
</handler>
</requestFlow>
This simple deployment descriptor signs and encrypts the SOAP Body part.
The only new parameter, signaturePropFile, specifies the
name of the signature crypto property file to use. Because no
encryptionPropFile is declared the handler also uses the signature
property file to get the encryption certificate. The same holds true for
the username. The password callback class must return a password
to get the user's private key (the keystore is defined in the crypto
property file) that WSS4J uses to generate the signature. The encryption
method uses the user's public key to encrypt the dynamically generated
session key.
The action parameter defines Signature Encryption.
Thus the handler first signs, then the encrypts the data.
Because the deployment descriptor does not contain specific encryption or
signature part parameters, WSS4J defaults to the data of the SOAP Body element.
Also all other parameters use their default setting, such as the format of the
key identifiers, encryption modifiers, and so on. Please refer to the
detailed
documentation of the parameters.
If the WSS4J Axis handler shall perform encryption only, then the
deployment descriptor must contain the encryption specific parameters. Only
if sign and encryption is required the encryption method falls back to
the signature parameters if the encryption specific parameters are not set.
The matching receiver deployment descriptor is also very simple:
<requestFlow>
<handler type="java:org.apache.ws.axis.security.WSDoAllReceiver">
<parameter name="passwordCallbackClass"
value="org.apache.ws.axis.oasis.PWCallback"/>
<parameter name="action" value="Signature Encrypt"/>
<parameter name="signaturePropFile" value="crypto.properties" />
</handler>
</requestFlow>
To reverse the actions, just reverse the action specifiers. The WSS4J
handler encrypts the SOAP Body first, then signs the encrypted data.
signatureParts and
encryptionParts control which SOAP elements to sign or
to encrypt. Please refer to the
detailed description of these parameters.
WSS4J signs or encrypts all declared parts using the same keys, that is
the signature or encryption data structures directly reference the
specified parts as described in the WSS specifications. The receiver
automatically detects these references and verfies and decrypts the
data parts. No special settings in the depolyment descriptor is necessary.
<requestFlow>
<handler type="java:org.apache.ws.axis.security.WSDoAllSender" >
<parameter name="action" value="Signature NoSerialization"/>
<parameter name="user" value="firstUser"/>
<parameter name="passwordCallbackClass"
value="org.apache.ws.axis.oasis.PWCallback"/>
<parameter name="signaturePropFile" value="crypto.properties" />
<parameter name="signatureParts" value="{}{http://xmlsoap.org/Ping}ticket" />
</handler>
<handler type="java:org.apache.ws.axis.security.WSDoAllSender" >
<parameter name="action" value="Signature"/>
<parameter name="user" value="anotherUser"/>
<parameter name="passwordCallbackClass"
value="org.apache.ws.axis.oasis.PWCallback"/>
<parameter name="signaturePropFile" value="crypto.properties" />
</handler>
</requestFlow>
Note the action specifier NoSerialization first handler.
In a handler chain of WSS4J handlers every
but the last handler must have this action specifier. This specifier
surpresses the very last step of the handler's security processing: the
serialization of the processed SOAP request in a XML string (document) that
Axis sends to the reveiver. Only the last handler must perform this
serialization.
Every handler specification can have its own set of parameters that define
the individual values for this handler instance. Thus the deployment
descriptor can define different crypto property files, different usernames,
and so on. In the example the first handler signs the ticket
element and the second handler the SOAP Body (default).
Parameters set by the application with setProperty are valid for
all handler instances in the handler
chain (setProperty is defined on the SOAP request (call) level).
As already decribed, deployment settings overrule application settings. Thus it
is possible to combine various parameter specifications. A special case is the
definition of the username. If an application sets the username and one
handler instance in the chain does not have a user parameter
in its deployment part, then this one handler instance uses the username set
bey the application. After the handler copied the username from the username
property, the handler sets the property's content to null.
Handlers that follow in the chain cannot use this username anymore and
must have a user (or encryption user) parameter in their deployment part.
Crypto implementation
(as defined in the crypto property file) must be able to handle all possible
certificates, users, passwords, and keys that a security header may contain.
The following deployment descriptor of a receiver shows this.
<requestFlow>
<handler type="java:org.apache.ws.axis.security.WSDoAllReceiver">
<parameter name="passwordCallbackClass"
value="org.apache.ws.axis.oasis.PWCallback"/>
<parameter name="action" value="Signature Signature"/>
<parameter name="signaturePropFile" value="crypto.properties" />
</handler>
</requestFlow>
The client uses two handlers in a chain, each signing a part of the SOAP
request but with different certificates. Because the handlers do not
specifiy a SOAP actor WSS4J puts both signatures in the security header
of the default actor.
To match the security actions the deployment descriptor of the receiver needs
to contain the action declaration Signature Signature. This
instructs the WSS4J handler to accept and verify two distinct signatures
contained in one security header. Because the signatures use different
certificates the Crypto implementation must be able to handle
these certificates.
Similar requirements are true for the password callback implementation if the
sender uses handler chaining and uses different encryption parameters in the
same security header.
If it is necessary to have different parameters for the distinct signature or
decryption data then these should be put in different security headers. The
easiest way to do this is to define different actor parameters
for each handler in a WSS4J handler chain.
WSSecurityEngine processes the security elements inside
a security header. If something goes wrong, for example a signature
verfication fails, then the engine throws a fault. If the security engine
could perform all operations sucessfully it returns a data structure
that contains the results of the performed security actions. This data
structure holds information about the performed action, the usernames or
identifier in case the security engine performed signature or username token
processing. Please refer to the
result structure.
The WSDoAllReceiver WSS4J handler takes this structure and
checks if all required actions were performed. If this check fails, the
WSS4J handler aborts the SOAP request and throws an Axis SOAP fault.
Otherwise it creates its own data structure
WSHandlerResult, copies the
security results in this structure, and adds the actor name of the
security header. Then it stores this new data structure in a vector and stores
this vector in a specific
property
of the current message context. If WSS4J handlers are
chained, then every handler in the chain adds its result to the vector. The
vector contains the results in handler-chain order.
This code snippet shows how a Axis service can access the security result
data:
public void ping(javax.xml.rpc.holders.StringHolder text,
org.apache.ws.axis.oasis.ping.TicketType ticket)
throws java.rmi.RemoteException {
text.value = "Echo " + text.value.trim();
// get the message context first
MessageContext msgContext = MessageContext.getCurrentContext();
Message reqMsg = msgContext.getRequestMessage();
Vector results = null;
// get the result Vector from the property
if ((results =
(Vector) msgContext.getProperty(WSHandlerConstants.RECV_RESULTS))
== null) {
System.out.println("No security results!!");
}
System.out.println("Number of results: " + results.size());
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());
}
}
}
}
The principal structure is either a
UsernameToken principal
or a X509Principal. The
princpals contain the names plus other information of the verified username
token or signature certificate.
Crypto implementation shall be
as fast as possible. In general, no user interaction is possible at the
server side to gather passwords. Also at this point of the SOAP request
processing there are active timeouts, even if they are fairly long.
WSDoAllSender on the
responseFlow at the server and WSDoAllReceiver
at the response flow of the client thus reversing the roles. Similar to
the above hints, the server side part (now WSDoAllSender)
runs in the server context and WSDoAllReceiver
runs in the application (client) context. There are no Axis timeout
constraints on the client side after Axis received the response
and handed it over to the WSS4J handler.
|
|||||||||||
| PREV PACKAGE NEXT PACKAGE | FRAMES NO FRAMES | ||||||||||