This document base on following version of applications:
Axis2 1.3, Rampart 1.3, Tomcat 5.5
If you get a higher version of them, this document maybe out of date for you.
1. Rampart setup
Axis2 comes with a module based on Apache WSS4J [1] to provide WS-Security features, called "Rampart".
Rampart is released as a module of Axis2, you should download it separately.
You can download the release of rampart1.3 at:
http://www.apache.org/dyn/mirrors/mirrors.cgi/ws/rampart/1_3/rampart-1.3.zip
For how to set up rampart, please refer to the readme.txt in the zip file you download. After that you should be engaged by inserting the following in the axis2.xml file at:
[your tomcat directory]/webapps/axis2/WEB-INF/conf.
<module ref="rampart"/>
2. Configuration
Rampart module uses two parameters:
OutflowSecurity
InflowSecurity
2.1 OutflowSecurity Parameter
This parameter is used to configure the outflow security handler. The outflow handler can be invoked more than once in the outflow one can provide configuration for each of these invocations. The 'action' element describes one of these configurations. Therefore the 'OutflowSecurity' parameter can contain more than one 'action' elements.
Following is a description of the elements that can go in an 'action' element of the OutflowSecurity parameter
Parameter | Description | Example |
items | Security actions for the inflow | Add a Timestamp, Sign the SOAP body and Encrypt the SOAP body |
user | The user's name | Set alias of the key to be used to sign |
passwordCallbackClass | Callback class used to provide the password required to create the UsernameToken or to sign the message | <passwordCallbackClass> org.apache.axis2.security.PWCallback</passwordCallbackClass> |
signaturePropFile | property file used to get the signature parameters such as crypto provider, keystore and its password | Set example.properties file as the signature property file |
signatureKeyIdentifier | Key identifier to be used in referring the key in the signature | Use the serial number of the certificate |
encryptionKeyIdentifier | Key identifier to be used in referring the key in encryption | Use the serial number of the certificate |
encryptionUser | The user's name for encryption. |
|
encryptionSymAlgorithm | Symmetric algorithm to be used for encryption | Use AES-128 |
encryptionKeyTransportAlgorithm | Key encryption algorithm | Use RSA-OAEP |
signatureParts | Sign multiple parts in the SOAP message | Sign Foo and Bar elements qualified by "http://app.ns/ns" |
optimizeParts | MTOM Optimize the elements specified by the XPath query | Optimize the CipherValue |
2.2 InflowSecurity Parameter
This parameter is used to configure the inflow security handler. The 'action' element is used to encapsulate the configuration elements here as well
Parameter | Description | Example |
items | Security actions for the inflow | first the incoming message should be decrypted and then the signatures should be verified and should be checked for the availability of the Timestamp |
passwordCallbackClass | Callback class used to obtain password for decryption and UsernameToken verification |
|
signaturePropFile | Property file used for signature verification |
|
decryptionPropFile | Property file used for decryption |
|
3. Use basic rampart configuration
Use basic rampart configuration need you change two configuration files. One is on the server side which zipped in the arr file called services.xml, the other is on the client side usually named axis2.xml.
3.1 No security
First let’s take a look at a simple web service without security.
The services.xml file on server:
<service> <operation name="echo"> <messageReceiver class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/> </operation> <parameter name="ServiceClass" locked="false"> org.apache.rampart.samples.sample01.SimpleService</parameter>
<module ref="rampart" /> </service> |
The axis2.xml file on client:
<axisconfig name="AxisJava2.0"> <module ref="rampart" /> …… other parameter we don’t care about </axisconfig> |
Request soap message:
<?xml version='1.0' encoding='UTF-8'?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Body> <ns1:echo xmlns:ns1="http://sample01.samples.rampart.apache.org"> <param0>Hello world</param0> </ns1:echo> </soapenv:Body> </soapenv:Envelope> |
Response soap message:
<?xml version='1.0' encoding='UTF-8'?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Body> <ns:echoResponse xmlns:ns="http://sample01.samples.rampart.apache.org"> <ns:return>Hello world</ns:return> </ns:echoResponse> </soapenv:Body> </soapenv:Envelope> |
As you see, there’s no security information attached in the soap message. There’s even no soapenv:header in the envelope.
3.2. Username token
“WS-Security 2004” defines the <wsse:Security> header as a mechanism for conveying security information with and about a SOAP message. This header is, by design, extensible to support many types of security information. For security tokens based on XML, the extensibility of the <wsse:Security> header allows for these security tokens to be directly inserted into the header.
Username token is the simplest token, you can use this type security easy with rampart.
The services.xml file on server:
<service> <operation name="echo"> <messageReceiver class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/> </operation> <parameter name="ServiceClass" locked="false"> org.apache.rampart.samples.sample03.SimpleService</parameter>
<module ref="rampart" /> <parameter name="InflowSecurity"> <action> <items>UsernameToken</items> <passwordCallbackClass>org.apache.rampart.samples.sample03.PWCBHandler</passwordCallbackClass> </action> </parameter> </service> |
The axis2.xml file on client:
<axisconfig name="AxisJava2.0"> <module ref="rampart" /> <parameter name="OutflowSecurity"> <action> <items>UsernameToken</items> <user>bob</user> <passwordCallbackClass>org.apache.rampart.samples.sample03.PWCBHandler</passwordCallbackClass> <passwordType>PasswordText</passwordType> </action> </parameter> …… other parameter we don’t care about </axisconfig> |
In the two configure file we learn that we only attach username security token in the messages from client to server. Also we should note that there is a node named “passwordCallbackClass” which indicate a java class. Of course no one will think put the username and password in the configure file is a good idea. So rampart need you write a callback class to validate the security information. Here’s the source code of this class:
package org.apache.rampart.samples.sample03;
import org.apache.ws.security.WSPasswordCallback; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; import java.io.IOException;
public class PWCBHandler implements CallbackHandler { public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) { //When the server side need to authenticate the user WSPasswordCallback pwcb = (WSPasswordCallback)callbacks[i]; if (pwcb.getUsage() == WSPasswordCallback.USERNAME_TOKEN_UNKNOWN) { if(pwcb.getIdentifer().equals("bob") && pwcb.getPassword().equals("bobPW")) { //If authentication successful, simply return return; } else { throw new UnsupportedCallbackException(callbacks[i], "check failed"); } } //When the client requests for the password to be added in to the //UT element pwcb.setPassword("bobPW"); } } } |
Request soap message:
<?xml version='1.0' encoding='UTF-8'?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Header> <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soapenv:mustUnderstand="1"> <wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="UsernameToken-22676229"> <wsse:Username>bob</wsse:Username> <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText"> bobPW</wsse:Password> </wsse:UsernameToken> </wsse:Security> </soapenv:Header> <soapenv:Body> <ns1:echo xmlns:ns1="http://sample03.samples.rampart.apache.org"> <param0>Hello world</param0> </ns1:echo> </soapenv:Body> </soapenv:Envelope> |
Here you may find the value of wsse:Password node is plain text. This is because the value of passwordType node defines PasswordText in the axis2.xml file.
For detail information about password type, please refer to:
http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0.pdf
Response soap message:
<?xml version='1.0' encoding='UTF-8'?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Body> <ns:echoResponse xmlns:ns="http://sample03.samples.rampart.apache.org"> <ns:return>Hello world</ns:return> </ns:echoResponse> </soapenv:Body> </soapenv:Envelope> |
3.3 Timestamps and Signatures
It is often important for the recipient to be able to determine the freshness of security semantics. In some cases, security semantics may be so stale that the recipient may decide to ignore it. This time information is added into security header as security timestamps. This is quite easy mechanism and you will understand it once you see the sample below.
Message producers may want to enable message recipients to determine whether a message was altered in transit and to verify that the claims in a particular security token apply to the producer of the message. So WS Security adds signature mechanism.
Below is a sample with both timestamps and signatures.
The services.xml file on server:
<service> <operation name="echo"> <messageReceiver class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/> </operation> <parameter name="ServiceClass" locked="false">org.apache.rampart.samples.sample04.SimpleService</parameter>
<module ref="rampart" />
<parameter name="InflowSecurity"> <action> <items>Timestamp Signature</items> <signaturePropFile>service.properties</signaturePropFile> </action> </parameter>
<parameter name="OutflowSecurity"> <action> <items>Timestamp Signature</items> <user>service</user> <passwordCallbackClass>org.apache.rampart.samples.sample04.PWCBHandler</passwordCallbackClass> <signaturePropFile>service.properties</signaturePropFile> <signatureKeyIdentifier>DirectReference</signatureKeyIdentifier> </action> </parameter> </service>
|
The axis2.xml file on client:
<axisconfig name="AxisJava2.0"> <module ref="rampart" /> <parameter name="OutflowSecurity"> <action> <items>Timestamp Signature</items> <user>client</user> <signaturePropFile>client.properties</signaturePropFile> <passwordCallbackClass>org.apache.rampart.samples.sample04.PWCBHandler</passwordCallbackClass> <signatureKeyIdentifier>DirectReference</signatureKeyIdentifier> </action> </parameter>
<parameter name="InflowSecurity"> <action> <items>Timestamp Signature</items> <signaturePropFile>client.properties</signaturePropFile> </action> </parameter>
…… other parameter we don’t care about </axisconfig> |
Here we need to give the property file in the signatiurePropFile node which is used to get the signature parameters such as crypto provider, keystore and its password.
service.properties:
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin org.apache.ws.security.crypto.merlin.keystore.type=jks org.apache.ws.security.crypto.merlin.keystore.password=apache org.apache.ws.security.crypto.merlin.file=service.jks |
client.properties:
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin org.apache.ws.security.crypto.merlin.keystore.type=jks org.apache.ws.security.crypto.merlin.keystore.password=apache org.apache.ws.security.crypto.merlin.file=service.jks |
If you want to learn more about signature mechanism and how to generate a java key store file (jks), please refer to other documents.
Request soap message:
<?xml version='1.0' encoding='UTF-8'?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Header> <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soapenv:mustUnderstand="1"> <wsse:BinarySecurityToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" wsu:Id="CertId-148082">MIICTD16JCnxc8t……</wsse:BinarySecurityToken> <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="Signature-22522451"> <ds:SignedInfo> <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" /> <ds:Reference URI="#id-9616314"> <ds:Transforms> <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> </ds:Transforms> <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /> <ds:DigestValue>VW/6XSiKAVACSGqN2J0RB9k2eGs=</ds:DigestValue> </ds:Reference> </ds:SignedInfo> <ds:SignatureValue> KnsDIYt2njqGDniofDIMUMDvssYqSfNdeTIbb7gNtusDViElF1+/Q50kW5Zeq4JvSSORpdxbYVf4 mmS1MGZ/OEacsAc4eYlWYY9tFK/kqBcoFIkcAcWMD2b9OKsaBjIKQelbv9nKPhYFEOOmcsPuqOzi x1PttUJUhodKbCMpUH0= </ds:SignatureValue> <ds:KeyInfo Id="KeyId-1603604"> <wsse:SecurityTokenReference xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="STRId-17103608"> <wsse:Reference URI="#CertId-148082" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" /> </wsse:SecurityTokenReference> </ds:KeyInfo> </ds:Signature> <wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="Timestamp-20243707"> <wsu:Created>2008-07-16T11:03:48.135Z</wsu:Created> <wsu:Expires>2008-07-16T11:08:48.135Z</wsu:Expires> </wsu:Timestamp> </wsse:Security> </soapenv:Header> <soapenv:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="id-9616314"> <ns1:echo xmlns:ns1="http://sample04.samples.rampart.apache.org"> <param0>Hello world</param0> </ns1:echo> </soapenv:Body> </soapenv:Envelope>
|
Response soap message:
<?xml version='1.0' encoding='UTF-8'?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Header> <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soapenv:mustUnderstand="1"> <wsse:BinarySecurityToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" wsu:Id="CertId-2150700">MIICTjCCAb……</wsse:BinarySecurityToken> <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="Signature-1418145"> <ds:SignedInfo> <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" /> <ds:Reference URI="#id-29532653"> <ds:Transforms> <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> </ds:Transforms> <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /> <ds:DigestValue>v1uKrYAcbqiLBnRvtbtGsQ60xcI=</ds:DigestValue> </ds:Reference> <ds:Reference URI="#SigConf-6958977"> <ds:Transforms> <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> </ds:Transforms> <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /> <ds:DigestValue>EuSL052N6IemNzEO0zFfpmjcB0g=</ds:DigestValue> </ds:Reference> </ds:SignedInfo> <ds:SignatureValue> TwHdD5JqEtAq8W55otx6D6oERFCLNcfgSHJgg/jxf0fttzgfZMOHzFFR73NUMcrwh6lXaOmyaHRJ Yf8TpC00y51j8GFkPJUAeMvihhRzUkvvZmiaaw/rF9JzphqZBRO1b0RffAH9i0zcRJPP9h9l6n2t lhvNzPGFgu1Ge0TaZXc= </ds:SignatureValue> <ds:KeyInfo Id="KeyId-18333931"> <wsse:SecurityTokenReference xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="STRId-8041484"><wsse:Reference URI="#CertId-2150700" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" /> </wsse:SecurityTokenReference> </ds:KeyInfo> </ds:Signature> <wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="Timestamp-7312507"> <wsu:Created>2008-07-16T11:03:49.479Z</wsu:Created> <wsu:Expires>2008-07-16T11:08:49.479Z</wsu:Expires> </wsu:Timestamp> <wsse11:SignatureConfirmation xmlns:wsse11="http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" Value="KnsDIYt2njqGDniofDIMUMDvssYqSfNdeTIbb7gNtusDViElF1+/Q50kW5Zeq4JvSSORpdxbYVf4mmS1MGZ/OEacsAc4eYlWYY9tFK/kqBcoFIkcAcWMD2b9OKsaBjIKQelbv9nKPhYFEOOmcsPuqOzix1PttUJUhodKbCMpUH0=" wsu:Id="SigConf-6958977" /> </wsse:Security> </soapenv:Header> <soapenv:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="id-29532653"> <ns:echoResponse xmlns:ns="http://sample04.samples.rampart.apache.org"> <ns:return>Hello world</ns:return> </ns:echoResponse> </soapenv:Body> </soapenv:Envelope>
|
4. Use WS-Security policy configuration
Alternatively, you can use WS-Security policy to create your web service. WS-Security policy language can be used to publish security requirements and constrains of a Web service using the WSDL specification. That is, using WS – security policy language, we can drive a Web service security engine to secure out going messages in a certain way and instruct the verification of incoming messages in a standard, defined way.
On the server side, we also need the services.xml file but more complex.
<service> <operation name="echo"> <messageReceiver class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/> </operation> <parameter name="ServiceClass" locked="false">org.apache.rampart.samples.policy.sample01.SimpleService</parameter>
<module ref="rampart" /> <module ref="addressing" />
<wsp:Policy wsu:Id="UTOverTransport" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"> <wsp:ExactlyOne> <wsp:All> <sp:TransportBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <wsp:Policy> <sp:TransportToken> <wsp:Policy> <sp:HttpsToken RequireClientCertificate="false"/> </wsp:Policy> </sp:TransportToken> <sp:AlgorithmSuite> <wsp:Policy> <sp:Basic256/> </wsp:Policy> </sp:AlgorithmSuite> <sp:Layout> <wsp:Policy> <sp:Lax/> </wsp:Policy> </sp:Layout> <sp:IncludeTimestamp/> </wsp:Policy> </sp:TransportBinding> <sp:SignedSupportingTokens xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <wsp:Policy> <sp:UsernameToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient" /> </wsp:Policy> </sp:SignedSupportingTokens>
<ramp:RampartConfig xmlns:ramp="http://ws.apache.org/rampart/policy"> <ramp:passwordCallbackClass> org.apache.rampart.samples.policy.sample01.PWCBHandler</ramp:passwordCallbackClass> </ramp:RampartConfig>
</wsp:All> </wsp:ExactlyOne> </wsp:Policy>
</service>
|
On the client side, we need a policy.xml corresponding to the services.xml:
<wsp:Policy wsu:Id="UTOverTransport" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"> <wsp:ExactlyOne> <wsp:All> <sp:TransportBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <wsp:Policy> <sp:TransportToken> <wsp:Policy> <sp:HttpsToken RequireClientCertificate="false"/> </wsp:Policy> </sp:TransportToken> <sp:AlgorithmSuite> <wsp:Policy> <sp:Basic256/> </wsp:Policy> </sp:AlgorithmSuite> <sp:Layout> <wsp:Policy> <sp:Lax/> </wsp:Policy> </sp:Layout> <sp:IncludeTimestamp/> </wsp:Policy> </sp:TransportBinding> <sp:SignedSupportingTokens xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <wsp:Policy> <sp:UsernameToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient" /> </wsp:Policy> </sp:SignedSupportingTokens>
<ramp:RampartConfig xmlns:ramp="http://ws.apache.org/rampart/policy"> <ramp:user> alice </ramp:user> <ramp:passwordCallbackClass> </ramp:RampartConfig>
</wsp:All> </wsp:ExactlyOne> </wsp:Policy>
|
<-----转贴请注明出处----->