您的位置:首页 > 运维架构 > Apache

Web Services Security with Apache Rampart – Part 1 ( Transport Level Security )

2012-04-05 13:54 579 查看


Web Services Security with Apache Rampart – Part 1 ( Transport Level Security )

Apache Rampart is the Axis2 module that provides WS-Security functionality to Axis2 Web services and their clients. Rampart currently implements WS-Security, WS-SecurityPolicy , WS-SecureConversation and WS-Trust specifications. In this tutorial, we will
look at applying transport level security to a Web service or a client using Apache Rampart.

Date: Thu, 7th Feb, 2008

Level: Introductory

Reads: 101376 Comments: 43 | Login or register to
post comments
Printer-friendly version

Send to friend

PDF version


Post
to twitter

Nandana Mihindukulasooriya

Tech Lead

WSO2 Inc.


Introduction

This tutorial is a step by step guide on how to use username token authentication with Apache Rampart using policy based configuration. We'll first look at a scenario. Then we'll look at deploying the Apache Rampart module in Axis2. We will then go on to look
at how a Axis2 web service and a client can be secured with Rampart. With Axis2/Rampart proven to be highly interoperable, either the Web service or the client can be also written and secured using some Web service stack other than Axis2/Java, such as .NET
, C or PHP. For example, Axis2 client with Rampart can be used to consume a secure .NET Web service.

Read Web Services Security with Apache Rampart – Part 2 (Message-Level Security)



Applies To

Apache Axis2/Java1.3
Apache Rampart/Java1.3



Table of Contents

Scenario
Deploying the Rampart Module

Deploying Rampart Module and Necessary Jars
Configuring SSL in Apache Tomcat

Securing the Service

Writing the Web Service and the Service Descriptor
Writing the Password Callback
Constructing the Security Policy
Engaging Rampart and Applying the Security Policy
Deploy the Service
Policy Annotated WSDL

Securing the Client

Generating the Stub using WSDL2Java Tool
Writing the Client
Engaging Rampart and Setting Authentication Information
Adding Server Certificate as a Trusted Certificate

Calling the Web Service

SOAP Messages Exchanged

Without Security
With Security

Summary
References
Resources


Scenario

In this tutorial, we will look at a scenario, where message protection is provided by the transport layer. All message exchanges will be done over the https transport. Clients will authenticate to the service using username tokens (usename/password).

We will use the Axis2 WAR deployed in Apache Tomcat server for this tutorial, as it is one of the most common use cases.




Deploying the Rampart Module


Step 1. Deploying the Module and Necessary Jars

Apache Rampart 1.3 binary distribution can be downloaded here. Rampart distribution contains two module files, rampart-1.3
and rahas-1.3.mar . These module files should be copied to the "modules" directory of Axis2, that can be found in TOMCAT_HOME/webapps/axis2/WEB-INF/modules, where, TOMCAT_HOME is the home directory of the Apache Tomcat server in which Axis2 war is deployed.
All the dependency jars needed for Apache Rampart can be found under the libs directory of the Rampart distribution. These has to be copied to the "lib" directory of Axis2, which can found under TOMCAT_HOME/webapps/axis2/WEB-INF/lib.

You can check whether Apache Rampart is successfully deployed by logging in to Axis2 as admin and using 'system components/available modules' option in admin Web console . Both "rampart" and "rahas" should be listed under available modules, if you have already
successfully deployed Rampart and Rahas modules.


Step 2. Configuring SSL in Apache Tomcat

In this tutorial, we use https transport in Apache Tomcat to provide transport. So we have to modify the server.xml of Apache Tomcat, which can be found in TOMCAT_HOME/conf directory, to include SSL configuration. You can use the server.jks keytore which can
be found in the source code zip file, as the keystore for this tutorial. Key store password is "password". SSL configuration in the server should
look like the one given below:
<!-- Define a SSL HTTP/1.1 Connector on port 8443 -->

<Connector port="8443" maxHttpHeaderSize="8192"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" disableUploadTimeout="true"
acceptCount="100" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS"
keystoreFile="path/to/server.jks"
keystorePass="password" />



Securing the Service


Step 1. Writing the Web Service and the Service Descriptor

For this tutorial, we will be using a simple service that has a single operation called "add", that adds two integers and returns the sum. For simplicity, we will be using the code first approach for this tutorial. Service implementation class is given below.

package tutorial.rampart.service;

/**
* Secure Service implementation class
*/
public class SecureService {

public int add(int a, int b) {
return a+b;
}

}


Service descriptor for the above mentioned service is given below. You can find more information on how to write an Axis2 Web service, in this tutorial: "Hello, World with
Apache Axis2".
<service>
<parameter name="ServiceClass" locked="false">tutorial.rampart.service.SecureService </parameter>
<operation name="add">
<messageReceiver class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
</operation>
</service>


Step 2. Writing the Password Callback

As we use username token authentication in this scenario, we need to write a password callback class, to be used by the Web service to authenticate username tokens. The password callback class which we use for this tutorial, is given below. Even though passwords
are hard coded in this example, passwords can be retrieved from a database, LDAP server or any storage, by writing the relevant password retrieval logic in the password callback class.
package tutorial.rampart.service;

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.getIdentifer().equals("apache") && pwcb.getPassword().equals("password")) {
//If authentication successful, simply return
return;
} else {
throw new UnsupportedCallbackException(callbacks[i], "check failed");
}

}
}

}


Step 3. Constructing the Security Policy

We will be using the policy based configuration approach in Apache Rampart for this tutorial. So we should construct a suitable security policy using WS-Security Policy Language, to define the requirements of the Web service. The security policy used in this
tutorial is given below:
<wsp:Policy wsu:Id="UsernameTokenOverHTTPS" 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>tutorial.rampart.service.PWCBHandler</ramp:passwordCallbackClass>
</ramp:RampartConfig>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>


As you can see, the above security policy contains two main security assertions, a transport binding assertion and a signed supporting token assertion. Transport binding assertion defines the requirement of using a SSL transport using the Https transport token
assertion. Signed supporting token defines, the requirement of a username token that should be integrity protected at the transport level. You can find more information on constructing a security policy in this article: "Understanding
WS-Security Policy Language" [3].

Last assertion, which is a Rampart specific assertion, is used to provide configuration details to Rampart. In the above policy, it defines a password callback class to be used. This assertion will not appear in WSDL.


Step 4. Engaging Rampart and Applying the Security Policy

Now, we will look at how we can engage Rampart to the Web service and apply the security policy. This is altogether done using the service descriptor. We don't have to modify the source of the Web service to secure it. First, we engage the Rampart module to
the Web service adding <module ref="rampart"/> element to the service descriptor. Then we apply security, by adding the policy to the service descriptor. Modified service descriptor after engaging rampart and applying policy, is given below. Elements with
the policy element is not shown for brevity.
<service>
<module ref="rampart"/>
<parameter name="ServiceClass" locked="false">tutorial.rampart.service.SecureService</parameter>
<operation name="add">
<messageReceiver class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
</operation>
<wsp:Policy wsu:Id="UsernameTokenOverHTTPS" 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:Policy>
</service>


Step 5. Deploy the Service

Now, we have to deploy this service in the Axis2 server. Create a service archive named SecureService.aar and drop it into the services directory which can found at: TOMCAT_HOME/webapps/axis2/WEB-INF/services, where, the TOMCAT_HOME is the home of Apache Tomcat
server. You can find information on how to create an Axis2 service archive in the "Hello, World with Axis2" tutorial [2] listed under references.


Policy Annotated WSDL

When a security policy is applied to Web service, the WSDL will be annotated with the relevant security policy so the clients can secure SOAP messages according to the policy defined in the WSDL. Code generators that generates stubs to access the Web service
can make use of these security policies defined in the WSDL. The policy annotated WSDL of the Web service we use for this tutorial can be found here.


Securing the Client


Step 1. Generating the Stub using WSDL2Java Tool

Java2WSDL tool provided by Axis2 can be used to generate stubs that can be used to call Web services. Given below is the command which we use in this tutorial to generate the stub. -uri option is used to provide the URL of the WSDL, -p option is used to specify
a custom package name for the code generated, -o option to specify a directory path for the code generated and -uw option to switch on un-wrapping.
[Linux]
$ sh WSDL2Java.sh -uri http://localhost:8080/axis2/services/SecureService?wsdl -p tutorial.rampart.client -uw  -o /project/path/

[Windows]
WSDL2Java.bat -uri http://localhost:8080/axis2/services/SecureService?wsdl -p tutorial.rampart.client -uw -o /project/to/path/



Step 2. Writting the Client

Now, we will write a client to the Web service using the stub generated. Source code of the client is given below:
package tutorial.rampart.client;

public class SecureServiceCGClient {

public static void main(String[] args) throws Exception {

SecureServiceStub stub = new SecureServiceStub(null,"https://localhost:8443/axis2/services/SecureService");

int a = 3;
int b = 4;

int result = stub.add(a, b);

System.out.println(a + " + " + b + " = " + result);
}
}



Step 3. Engaging Rampart and Setting Authentication Information

To secure SOAP request made by the client, we need to engage the Rampart module to the client. So we have to create a client repository and the rampart-1.3.mar should be deployed in the modules directory. We should make sure that all dependency .jar files of
the Apache Rampart module are in the classpath of the client. Then we can use the following code to engage Rampart in the client. Note that username and password to be used in the Username token, is provided using the Options class.

As you can see, we don't have to apply the policy to the client manually. WSDL2Java tool does that for us. It extracts the relevant policy from the WSDL and apply it correctly to the generatd stub.
// Rampart module should be in the repository
ConfigurationContext ctx = ConfigurationContextFactory.createConfigurationContextFromFileSystem("path/to/client/repo", null);

SecureServiceStub stub = new SecureServiceStub(ctx,"https://localhost:8443/axis2/services/SecureService");

ServiceClient sc = stub._getServiceClient();

sc.engageModule("rampart");

Options options = sc.getOptions();
options.setUserName("apache");
options.setPassword("password");


Step 4. Adding Server Certificate as a Trusted Certificate

As we are using HTTPS as the transport protocoal , SSL handshake has to happen and the client need to trust the server's certificate. We have to add the key store containg the server's certificate as a trust store and it can be done by seting the following
system properties:
System.setProperty("javax.net.ssl.trustStore", "/path/to/server.jks");
System.setProperty("javax.net.ssl.trustStorePassword", "password");//the storepass for the jks


NOTE: We only have to do this since we are using a self signed certificate. In a situation where the SSL channel is secured using a certificate signed by a known CA (Ceritificate Authority) we don't have to set these JSSE (Java Secure Socket Extension) properties.


Step 5. Calling the Web Service

Now, everything is well set and you can run the client and consume the Web service.


SOAP Messages Exchanged

We will take a look at the SOAP messages exchanged between the client and the service.


Without Security

This is SOAP message sent by the client without security;
<soapenv:Envelope>
<soapenv:Body>
<ns1:add
xmlns:ns1="http://service.rampart.tutorial">
<ns1:a>4</ns1:a>
<ns1:b>6</ns1:b>
</ns1:add>
</soapenv:Body>
</soapenv:Envelope>


With Security

This is the SOAP message sent by the client when Rampart is engaged and the above security policy applied. As you can see, SOAP header with a security header, is added to the SOAP message. Security header is used to send all security claims required by the
security policy of the server.
<soapenv:Envelope>
<soapenv:Header>
<wsse:Security
soapenv:mustUnderstand="1">
<wsu:Timestamp
wsu:Id="Timestamp-31497899">
<wsu:Created>2008-02-06T13:39:50.943Z</wsu:Created>
<wsu:Expires>2008-02-06T13:44:50.943Z</wsu:Expires>
</wsu:Timestamp>
<wsse:UsernameToken
wsu:Id="UsernameToken-10697954">
<wsse:Username>apache</wsse:Username>
<wsse:Password
Type="http://...#PasswordText">password</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<ns1:add
xmlns:ns1="http://service.rampart.tutorial">
<ns1:a>4</ns1:a>
<ns1:b>6</ns1:b>
</ns1:add>
</soapenv:Body>
</soapenv:Envelope>



Summary

In this tutorial, we looked at how to deploy Apache Rampart module and apply security to a Web service. We aslo looked at how to consume a secure Web service.

In part II of this tutorial "Web services security with Apache Rampart - Part II ( Message level security), we will look at how to secure Web services with Apache
Rampart using message level security. We will look at how to sign and encrypt various message parts, using Apache Rampart.


References

Apache Tomcat SSL configuration
Hello World with Apache Axis2
Understanding the WS Security Policy Language
Web Services Security with Apache Rampart – Part 2 (Message-Level Security)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: