Security and how to properly secure a Web service application is one of the most important issues facing developers charged with building Web service systems. Unfortunately, this is also an area of tremendous flux. The security standards specifications are yet to be fully fleshed out and, not surprisingly, commercial infrastructure does not yet provide good implementations of these security specifications.
WS-Security together with the other WS-* specifications are becoming the de facto standard for establishing secure, trust relationships within Web service environments. In the long-term, all Web service applications will use WS-Security to implement transport-independent, secure communications between client applications and Web services.
Until the WS-* specifications are fully completed and good commercial implementations are available, alternative security solutions are necessary. Waiting to add security until these specifications are complete and building Web services that do not use encryption or any sort of authorization is probably not a good idea. Luckily, for the majority of Web service applications today, the use of standard HTTP security mechanisms will suffice. Over the next few years, as Web services are used in larger and broader environments, the HTTP security mechanisms will need to be replaced by implementations of WS-Security.
In the remainder of this section, we look at how to secure our procurement application by using HTTP security mechanisms, including SSL and basic authorization. See Chapter 8 for a detailed coverage of WS-Security as well as the underlying XML security specifications, including XML Encryption and XML Digital Signatures.
HTTP security mechanisms are well-understood and proven technologies that have been used for years to secure Web sites. As we discussed in Chapter 8, although they work well for securing Web sites, HTTP security mechanisms have several shortcomings when used within a Web services environment. Nonetheless, until the WS-Security specifications are completed and fully implemented, for most Web services today, HTTP security presents a viable solution for data protection and authorization.
Web service transactions can be secured by using the following HTTP security techniques:
HTTP with Secure Sockets Layer (SSL), commonly referred to as HTTPS, for data protection.
HTTP basic authorization using usernames and passwords for access control and overall authorization.
Together, these two techniques provide a near-complete, point-to-point HTTP transport-level security solution for Web services. The aspect of security that is not covered by these two techniques is non-repudiation. Luckily, for the vast majority of Web service applications today, this is not critical.
We start by describing the steps necessary to configure support for HTTP basic authorization using username and password for access to the Web services of the EPS application. The configuration steps are as follows:
Define user credentials.
Credentials, in this case, are username and password pairs that are associated with different "roles" that are granted access to various protected resources. For our purposes, these protected resources are Web services, and potential users must present the appropriate username-password pair before they are given access to consume the Web service.
To define new user credentials, we must edit the %TOMCAT_HOME%\conf\ tomcat-users.xml file. Add a new role named webserviceauthorized, and specify its username as wsuser and its associated password as wsuserpw. The default tomcat-users.xml file with the required additions is shown below:
<?xml version='1.0' encoding='utf-8'?> <tomcat-users> <role rolename="tomcat"/> <role rolename="role1"/> <role rolename="manager"/> <role rolename="admin"/> <user username="tomcat" password="tomcat" roles="tomcat"/> <user username="both" password="tomcat" roles="tomcat,role1"/> <user username="role1" password="tomcat" roles="role1"/> <user username="admin" password="admin" roles="admin,manager"/> <!-- Add new usernames and passwords for new roles here --> <user username="wsuser" password="wsuserpw" roles="webserviceauthorized"/> </tomcat-users>
Provide a security constraint for each set of Web service URLs.
In this step, we associate a security constraint for the role we defined in the previous step for all Web services that are available from this Tomcat server. In particular, we specify that all Web services that are available on this Tomcat server whose endpoint URL includes the pattern /services/* will only be accessible to those users that belong to the webserviceauthorized role (created in the previous step).
To do this, we must edit the %TOMCAT_HOME%\webapps\axis\WEB-INF\ web.xml file. Add the following lines to immediately before the closing </web-app> element:
<security-constraint> <web-resource-collection> <web-resource-name> Protected Web Services </web-resource-name> <!-- Specify the URL pattern for the protected Web Services --> <url-pattern>/services/*</url-pattern> </web-resource-collection> <auth-constraint> <!-- Specify the role name to be associated with this security constraint --> <role-name>webserviceauthorized</role-name> </auth-constraint> </security-constraint> <!-- Specify the login configuration --> <login-config> <auth-method>BASIC</auth-method> <realm-name>Protected Web Services</realm-name> </login-config>
Specify the username and password within the client application.
Now that we have configured Tomcat and Axis to verify the username and password before allowing access to any of the Web services, we must make sure that each time our client application invokes a Web service it provides the appropriate username-password pair as part of the SOAP request.
We do this by setting the username and password within the call object of the invocation. If you are invoking Web services directly from the client application (without using client-side binding stubs), then add the following lines to the call object of the invocation. If you are using client-side binding stubs (as we are in the EPS application), then add the following two lines to the binding stubs of each of the Web services used by the application.
Now we have fully configured the Web services as well as the client application to use HTTP basic authentication based on the username-password pair: wsuser-wsuserpw. Only those SOAP messages that use HTTP as their transport and incorporate this username-password pair as part of the HTTP header will be allowed access to any of the Web services.
Next, we look at the steps necessary to configure support for HTTPS for exchange of SOAP messages. The configuration steps are as follows:
Download and install the Java Secure Socket Extension (JSSE) package. If your Java JDK is 1.4.0 or above, the JSSE is already bundled with the distribution and there is no need to download any additional package.
Create or obtain a SSL certificate that will be used to authenticate and encrypt data within the exchanged SOAP messages. Refer to Chapter 8 for an overview of the concepts underlying SSL, certificates, authentication, and encryption.
If you do not have or cannot obtain a certificate from a Certificate Authority, java provides a tool to generate and sign your own digital certificate. To run this tool, type in the following command:
JAVA_HOME%\bin\keytool -genkey -alias tomcat -keyalg RSA
The tool will prompt you to enter a variety of information about yourself and your organization that will be the basis for the generated certificate. The tool will also ask for a password. Although any password can be used, the default password used by Tomcat is changeit. The result of running this tool will be a file named .keystore locate on the user's home directory.
A certificate will need to be created for both the server (where the Web services are) and for the client. If both reside on a single machine (a rare case in most enterprise deployments), a single certificate can be used.
Enable SSL support on Tomcat.
To enable support for SSL on Tomcat, simply delete the comment tags around the following connector element within the %TOMCAT_HOME%\conf\ server.xml file:
<!-- Define a SSL Coyote HTTP/1.1 Connector on port 8443 --> <!-- Delete this line to enable SSL support <Connector className= "org.apache.coyote.tomcat4.CoyoteConnector" port="8443" minProcessors="5" maxProcessors="75" enableLookups="true" acceptCount="100" debug="0" scheme="https" secure="true" useURIValidationHack="false" disableUploadTimeout="true"> <Factory className= "org.apache.coyote.tomcat4.CoyoteServerSocketFactory" clientAuth="false" protocol="TLS" /> </Connector> Delete this line to enable SSL support -->
Modify the client application to access each Web service using HTTPS.
To instruct the client application to use HTTPS to communicate with each Web service, the endpoint of each Web service must be updated to include the HTTPS protocol and the port number 8443, which is the default configured port on which Tomcat listens for secure connections. To do this, change each Web service endpoint from http://<hostname>:8080/<Web service path> to https://<hostname>:8443/<Web service path>.
For instance, in the EPS application, the endpoint:
would be changed to:
Then finally, specify the location of the client SSL certificate for use during message authentication and encryption. If you are invoking Web services directly from the client application (without using client-side binding stubs), add the following line prior to instantiating the service object and creating the call object. If you are using client-side binding stubs (as we are in the EPS application), add the following line to the binding stubs of each of the Web services used by the application:
System.setProperty("javax.net.ssl.trustStore", "C:\\Documents and Settings\\Administrator\\.keystore");
Together, the specification of the HTTPS within the Web service endpoint and the specification of the location of the client certificate should be done as follows:
// Add these two lines String endpoint = "https://localhost:8443/axis/services/VendorAProcurement"; System.setProperty("javax.net.ssl.trustStore", "C:\\Documents and Settings\\sandeep\\.keystore"); // The above lines should be generally placed before // the new service is instantiated (below), either // within the client application (if client-side // binding stubs are not used), or within the // binding stubs (if they are used). Service service = new Service (); Call call = ( Call ) service.createCall (); call.setTargetEndpointAddress ( new java.net.URL ( endpoint ) ); // Invocation code...
On completing these steps, the application is configured for secure communications over a point-to-point HTTPS channel. HTTP basic authentication over SSL-based HTTPS provides a security solution that is sufficient for most Web service environments today. Together, these two HTTP security mechanisms provide the following capabilities within a Web service environment: message authentication, authorization, confidentiality, and integrity.