Java Web services: WS-Security with Metro--referenc
As you know from "Introducing Metro," the reference implementations of the JAXB 2.x data-binding and JAX-WS 2.x Web services standards are at the core of the Metro Web services framework. But in and of themselves, JAXB and JAX-WS provide only basic Web services support. JAX-WS doesn't cover the WS-* technologies that upgrade SOAP to work in enterprise environments, so other software components are needed to add support for these technologies.
About this series
Web services are a crucial part of Java technology's role in enterprise computing. In this series of articles, XML and Web services consultant Dennis Sosnoski covers the major frameworks and technologies that are important to Java developers using Web services. Follow the series to stay informed of the latest developments in the field and aware of how you can use them to aid your programming projects.
In Metro, the main added component is Web Services Interoperability Technologies (WSIT). WSIT is the current incarnation of what was originally known as Project Tango — Sun's effort to ensure interoperability of WS-* features, including security and reliable messaging, with the Microsoft .NET platform. WSIT provides Metro with support for WS-SecurityPolicy, WS-Trust, WS-SecureConversation, WS-ReliableMessaging, and more. The actual runtime handling of WS-Security is implemented by another added component, the XML and WebServices Security Project (XWSS).
This article shows how to use and configure WS-Security with Metro for stand-alone use as a Web application (outside of the Glassfish server). See Download to get the complete source code for the article's examples, which implement the simple library-management service used previously in this series.
WSIT basics
WSIT is responsible for configuring the Metro runtime to match the WS-Policy specifications for a service, including WS-Policy extensions such as WS-SecurityPolicy. Besides the standard WS-Policy extensions, Metro also uses custom extensions in policy documents to configure user information (such as key store locations and passwords) needed to implement security handling.
WSIT gets the policy information from a Web Services Description Language (WSDL) service description. On the client side, this can be confusing, because the WSDL used for the WSIT configuration is separate from the WSDL used to define the service for JAX-WS. As discussed in "Introducing Metro," the WSDL used to configure the JAX-WS client is obtained either directly from the service or from a location specified when you generate the JAX-WS code. The WSDL that WSIT uses has a fixed file name (though this file can use a <wsdl:import>
to reference a separate file with the full WSDL), and is always accessed from the classpath.
On the server side, WSIT requires a WSDL to be provided at a location specified by the WEB-INF/sun-jaxws.xml configuration file (discussed in "Introducing Metro"). The supplied WSDL must include the custom extensions used to configure user information for WSIT, but these custom extensions are deleted from the version of the WSDL provided in response to HTTP GET requests to the service endpoint.
The custom extensions used to configure WSIT user information look the same on the client and server sides but differ in the XML namespace used for the extension elements. On the client, this namespace is http://schemas.sun.com/2006/03/wss/client
; on the server the namespace is http://schemas.sun.com/2006/03/wss/server
.
UsernameToken
in Metro
"Axis2 WS-Security basics" introduced WS-Security in Axis2/Rampart with the simple case of a UsernameToken
. UsernameToken
provides a standard way of representing a username and password pair with WS-Security. The password information can be sent as plain text (normally, used in production only when combined with Transport Layer Security [TLS] or WS-Security encryption — but convenient for testing) or as a hash value.
To implement a simple plain-text UsernameToken
example on Metro, you need to use a WSDL service definition with the appropriate WS-Policy/WS-SecurityPolicy configuration included. Listing 1 shows an edited version of the same basic WSDL service definition used in "Introducing Metro," this time including policy information to require UsernameToken
on requests from the client to the server. The policy reference in the<wsdl:binding>
is shown in bold, as is the policy itself.
Listing 1. Plain-text UsernameToken
WSDL
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="http://ws.sosnoski.com/library/wsdl"
xmlns:wns="http://ws.sosnoski.com/library/wsdl"
xmlns:tns="http://ws.sosnoski.com/library/types"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/">
<wsdl:types>
...
</wsdl:types> <wsdl:message name="getBookRequest">
<wsdl:part element="wns:getBook" name="parameters"/>
</wsdl:message>
... <wsdl:portType name="Library">
<wsdl:operation name="getBook">
<wsdl:input message="wns:getBookRequest" name="getBookRequest"/>
<wsdl:output message="wns:getBookResponse" name="getBookResponse"/>
</wsdl:operation>
...
</wsdl:portType> <wsdl:binding name="LibrarySoapBinding" type="wns:Library"> <wsp:PolicyReference xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
URI="#UsernameToken"/> <wsdlsoap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="getBook">
<wsdlsoap:operation soapAction="urn:getBook"/>
<wsdl:input name="getBookRequest">
<wsdlsoap:body use="literal"/>
</wsdl:input>
<wsdl:output name="getBookResponse">
<wsdlsoap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
...
</wsdl:binding> <wsdl:service name="MetroLibrary">
<wsdl:port binding="wns:LibrarySoapBinding" name="library">
<wsdlsoap:address location="http://localhost:8080/metro-library-username"/>
</wsdl:port>
</wsdl:service> <!-- Policy for Username Token with plaintext password, sent from client to
server only -->
<wsp:Policy wsu:Id="UsernameToken" 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:SupportingTokens
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:Policy>
<sp:UsernameToken sp:IncludeToken=".../IncludeToken/AlwaysToRecipient"/>
</wsp:Policy>
</sp:SupportingTokens>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy> </wsdl:definitions>
The Listing 1 WSDL tells anyone who wants to access the service what needs to be done in terms of the security handling. You also need to add WSIT custom extensions to the policy information on both client and server sides with user-configuration details to indicate how the security handling will be implemented. These custom extensions fit into the <wsp:Policy>
components of the WSDL. Next I'll show you examples of these extensions for each side.
Client-side usage
On the client side, a file with the (fixed) name of wsit-client.xml is used for the WSIT configuration. This file must reside in a root directory (outside any package) on the classpath, or in a META-INF subdirectory of a directory in the classpath. And wsit-client.xml must be a WSDL document that either provides the full service WSDL directly or references a separate WSDL service definition using a <wsdl:import>
. Either way, the WSDL must include both the full WS-Policy/WS-SecurityPolicy requirements and the WSIT configuration extensions.
Listing 2 shows the policy section of the Listing 1 WSDL, with a WSIT custom extension added to configure the client-side UsernameToken
support. In this case, that custom extension is the <wssc:CallbackHandlerConfiguration>
element and child elements, shown in bold. The two child <wssc:CallbackHandler>
elements define callback classes, the first for the username (name="usernameHandler"
) and the second for the password (name="passwordHandler"
). The specified class(es) must implement thejavax.security.auth.callback.CallbackHandler
interface.
Listing 2. UsernameToken
policy with WSIT client-side extensions
<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsu=
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
wsu:Id="UsernameToken">
<wsp:ExactlyOne>
<wsp:All>
<sp:SupportingTokens
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:Policy>
<sp:UsernameToken sp:IncludeToken=".../IncludeToken/AlwaysToRecipient"/>
</wsp:Policy>
</sp:SupportingTokens>
<wssc:CallbackHandlerConfiguration wspp:visibility="private"
xmlns:wssc="http://schemas.sun.com/2006/03/wss/client"
xmlns:wspp="http://java.sun.com/xml/ns/wsit/policy">
<wssc:CallbackHandler name="usernameHandler"
classname="com.sosnoski.ws.library.metro.UserPassCallbackHandler"/>
<wssc:CallbackHandler name="passwordHandler"
classname="com.sosnoski.ws.library.metro.UserPassCallbackHandler"/>
</wssc:CallbackHandlerConfiguration>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
In Listing 2, both callbacks use the same class. Listing 3 shows the callback-class code, which just checks the type of each callback request and sets the appropriate value:
Listing 3. Client callback code
public class UserPassCallbackHandler implements CallbackHandler
{
public void handle(Callback[] callbacks) throws UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
if (callbacks[i] instanceof NameCallback) {
((NameCallback)callbacks[i]).setName("libuser");
} else if (callbacks[i] instanceof PasswordCallback) {
((PasswordCallback)callbacks[i]).setPassword("books".toCharArray());
} else {
throw new UnsupportedCallbackException(callbacks[i],
"Unsupported callback type");
}
}
}
}
You don't have to use a callback for either the username or the password. If you're using fixed values for these you can instead set them directly in the corresponding <wssc:CallbackHandler>
elements by replacing the classname="xxx"
attributes with default="yyy"
attributes (where the attribute value is the actual username or password).
Server-side usage
On the server side, the WSIT configuration information needs to be present in the WSDL service definition. As discussed in "Introducing Metro," the location of a service WSDL can be specified as a parameter in the WEB-INF/sun-jaxws.xml within the service WAR file. This WSDL is optional if you're not using WSIT features, in which case a WSDL will be generated automatically at run time. If you're using WSIT features, the WSDL is required and must include any custom extension elements necessary to configure WSIT for the features used by the service. Listing 4 shows the policy section of the Listing 1 WSDL, this time with a WSIT custom extension added to configure the server-side UsernameToken
support (shown in bold):
Listing 4. UsernameToken
policy with WSIT server-side extensions
<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsu=
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
wsu:Id="UsernameToken">
<wsp:ExactlyOne>
<wsp:All>
<sp:SupportingTokens
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:Policy>
<sp:UsernameToken sp:IncludeToken=".../IncludeToken/AlwaysToRecipient"/>
</wsp:Policy>
</sp:SupportingTokens>
<wsss:ValidatorConfiguration wspp:visibility="private"
xmlns:wsss="http://schemas.sun.com/2006/03/wss/server"
xmlns:wspp="http://java.sun.com/xml/ns/wsit/policy">
<wsss:Validator name="usernameValidator"
classname="com.sosnoski.ws.library.metro.PasswordValidator"/>
</wsss:ValidatorConfiguration>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
The server-side WSIT extension in Listing 4 takes the form of a <wsss:ValidatorConfiguration>
element and child <wsss:Validator>
element, specifying the class to be used as a validator callback. Listing 5 shows the code for this class, which must implement thecom.sun.xml.wss.impl.callback.PasswordValidationCallback.PasswordValidator
interface. In this case, it just checks the supplied username and password against fixed values, but it could easily use a database lookup or other mechanism instead.
Listing 5. Server callback code
public class PasswordValidator implements PasswordValidationCallback.PasswordValidator
{
public boolean validate(Request request) throws PasswordValidationException {
PasswordValidationCallback.PlainTextPasswordRequest ptreq
= (PasswordValidationCallback.PlainTextPasswordRequest)request;
return "libuser".equals(ptreq.getUsername()) &&
"books".equals(ptreq.getPassword());
}
}
Metro policy tool
Metro/WSIT requires you to add configuration information to your WSDLs, just as with Axis2/Rampart. The earlier articles in this series covering Axis2/Rampart used a special policy tool during the build process to generate modified WSDLs as needed. A similar tool, designed around the needs of Metro/WSIT, is included in the example-code downloadfor this article.
This tool is the com.sosnoski.ws.MergeTool
application, in the mergetool directory of the sample code. MergeTool merges data into a target XML document, matching nested XML elements to find the data to be merged and to determine the merge point in the target document. The sample application's build.xml uses MergeTool to add WSIT configuration information for the client or server into the WSDL for the service. You can also use MergeTool in your own applications, if you wish — the mergetool/readme.txt file contains some basic usage information, and you can also see the way it's used in the supplied build.
If you don't supply a <wsss:ValidatorConfiguration>
, Metro will use the authorization mechanism supplied by your Web application container (the Web server providing servlet support).
Building and running the sample code
Before you can try out the sample code, you need to download and install a current version of Metro (the code was tested with the 1.5 release) on your system (see Resources). You also need to edit the build.properties file in the root directory of the unzipped sample-code downloadto change the value of the metro-home
property to the path to your Metro installation. If you're going to be testing with a server on a different system or port, you may also want to change thehost-name
and host-port
.
To build the sample application using the supplied Ant build.xml, open a console to the root directory of the download code and type ant
. This will first invoke the JAX-WS wsimport
tool (included in the Metro distribution), then compile the client and server, and finally package the server code as a WAR (generating separate versions of the service WSDL containing client and server WSIT configuration information in the process). Note that the version of wsimport
included in Metro 1.5 will issue a warning message (because of a quirk in the tool's processing of schemas embedded in WSDL): src-resolve: Cannot resolve the name 'tns:BookInformation' to a(n) 'type definition' component
.
You can then deploy the generated metro-library.war file to your test server, and finally type ant run
on the console to try running the sample client. The sample client runs through a sequence of several requests to the server, printing brief results for each request.
Signing and encrypting in Metro
UsernameToken
's simplicity makes it a good starting point, but it isn't a typical use of WS-Security. Most often, you'll use either signatures or encryption, or both. Listing 6 shows an edited example of WSDL using both signatures and encryption (based on an example from "Axis2 WS-Security signing and encryption" — see that article for a more detailed discussion of WS-Security signing and encryption in general). The policy portions of the WSDL are shown in bold.
Listing 6. Signing/encrypting WSDL
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="http://ws.sosnoski.com/library/wsdl"
xmlns:wns="http://ws.sosnoski.com/library/wsdl"
xmlns:tns="http://ws.sosnoski.com/library/types"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/">
<wsdl:types>
...
</wsdl:types> <wsdl:message name="getBookRequest">
<wsdl:part element="wns:getBook" name="parameters"/>
</wsdl:message>
... <wsdl:portType name="Library">
<wsdl:operation name="getBook">
<wsdl:input message="wns:getBookRequest" name="getBookRequest"/>
<wsdl:output message="wns:getBookResponse" name="getBookResponse"/>
</wsdl:operation>
...
</wsdl:portType> <wsdl:binding name="LibrarySoapBinding" type="wns:Library"> <wsp:PolicyReference xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
URI="#SignEncr"/> <wsdlsoap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="getBook">
<wsdlsoap:operation soapAction="urn:getBook"/>
<wsdl:input name="getBookRequest">
<wsdlsoap:body use="literal"/>
</wsdl:input>
<wsdl:output name="getBookResponse">
<wsdlsoap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
...
</wsdl:binding> <wsdl:service name="MetroLibrary">
<wsdl:port binding="wns:LibrarySoapBinding" name="library">
<wsdlsoap:address location="http://localhost:8080/metro-library-username"/>
</wsdl:port>
</wsdl:service> <!-- Policy for first signing and then encrypting all messages, with the certificate
included in the message from client to server but only a thumbprint on messages from
the server to the client. -->
<wsp:Policy wsu:Id="SignEncr" 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:AsymmetricBinding
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:Policy>
<sp:InitiatorToken>
<wsp:Policy>
<sp:X509Token sp:IncludeToken=".../IncludeToken/AlwaysToRecipient">
<!-- Added this policy component so Metro would work with the same
certificates (and key stores) used in the Axis2/Rampart example. -->
<wsp:Policy>
<sp:RequireThumbprintReference/>
</wsp:Policy>
</sp:X509Token>
</wsp:Policy>
</sp:InitiatorToken>
<sp:RecipientToken>
<wsp:Policy>
<sp:X509Token sp:IncludeToken=".../IncludeToken/Never">
<wsp:Policy>
<sp:RequireThumbprintReference/>
</wsp:Policy>
</sp:X509Token>
</wsp:Policy>
</sp:RecipientToken>
<sp:AlgorithmSuite>
<wsp:Policy>
<sp:TripleDesRsa15/>
</wsp:Policy>
</sp:AlgorithmSuite>
<sp:Layout>
<wsp:Policy>
<sp:Strict/>
</wsp:Policy>
</sp:Layout>
<sp:IncludeTimestamp/>
<sp:OnlySignEntireHeadersAndBody/>
</wsp:Policy>
</sp:AsymmetricBinding>
<sp:SignedParts
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<sp:Body/>
</sp:SignedParts>
<sp:EncryptedParts
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<sp:Body/>
</sp:EncryptedParts>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy> </wsdl:definitions>
The only significant difference between the Listing 6 WSDL and that used in the earlier Axis2/Rampart example is the addition of a policy to the<sp:InitiatorToken>
component to require using a thumbprint reference when the X.509 certificate is not included in a message. This addition is required due to differences in how references are handled by default in Metro and Axis2.
When the client (the initiator, in WS-SecurityPolicy-speak) sends a message, the X.509 certificate for the client is sent as part of the message (because of the sp:IncludeToken=".../IncludeToken/AlwaysToRecipient"
attribute on the<sp:InitiatorToken/wsp:Policy/sp:X509Token>
element) and used by the server to verify signatures. When the server replies to the client, it needs to reference that same certificate from the client as used in the encryption processing. Axis2/Rampart defaults to using a thumbprint reference for the certificate identification, if no other method is specified. Metro/WSIT defaults to using another method, called subject key identifier(SKI). The certificates used in the Axis2/Rampart example were of a form that did not support SKI, so they won't work with Metro/WSIT by default. Adding the <sp:RequireThumbprintReference/>
element to the policy tells Metro/WSIT to use a thumbprint reference instead for the certificate.
This change to the policy allows the same certificates and key stores used in the earlier Axis2/Rampart example to be used for this example. That in turn allows the Axis2/Rampart client example to be used with the Metro/WSIT server, and vice versa, as a convenient way of checking interoperability. If you try this out (which you can do by changing the target path passed to the test client in each case) you'll find that for the most part the messages are exchanged without difficulty — but with one difference in operation, discussed in the Interoperability issue section, below.
As with the UsernameToken
example, WSIT needs custom extensions to the policy information on both client and server sides to provide additional configuration details.
Client-side usage
Listing 7 shows the WSIT custom extensions added to the WSDL policy to configure the client-side handling for the example. These custom extensions, shown in bold, configure the key store (containing the client's private key and corresponding certificate) and the trust store (containing the server's certificate) needed for the signing and encryption.
Listing 7. Signing and encrypting policy with WSIT client-side extensions
<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsu=
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
wsu:Id="SignEncr">
<wsp:ExactlyOne>
<wsp:All>
<sp:AsymmetricBinding xmlns:sp=
"http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:Policy>
...
</wsp:Policy>
</sp:AsymmetricBinding>
<sp:SignedParts
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<sp:Body/>
</sp:SignedParts>
<sp:EncryptedParts
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<sp:Body/>
</sp:EncryptedParts> <wssc:KeyStore alias="clientkey" keypass="clientpass"
location="client.keystore" storepass="nosecret"
xmlns:wspp="http://java.sun.com/xml/ns/wsit/policy" wspp:visibility="private"
xmlns:wssc="http://schemas.sun.com/2006/03/wss/client"/>
<wssc:TrustStore location="client.keystore" peeralias="serverkey"
storepass="nosecret" xmlns:wspp="http://java.sun.com/xml/ns/wsit/policy"
wspp:visibility="private"
xmlns:wssc="http://schemas.sun.com/2006/03/wss/client"/>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
The Listing 7 WSIT custom extensions give all the necessary parameters for accessing the key store and trust store (which in this case are the same file), including the password required for accessing the client's private key (the keypass="clientpass"
attribute on the<wssc:KeyStore>
element). It's also possible to use a callback for password information, as you'll see in the next section.
The named key store and trust store must be in a META-INF child directory of a directory in the classpath. You can also use absolute file paths for these files — rather than just a file name — which lets you locate them at any fixed location on your file system. (Recall that for the client, the WSDL including the WSIT custom extensions must use the fixed name wsit-client.xml and must be either in a root directory of the classpath, or in a META-INF child directory of a root directory in the classpath.)
Server-side usage
The server-side WSIT custom extensions added to the WSDL are shown in Listing 8 (again in bold). In this case the <wsss:KeyStore>
'skeypass
attribute gives a class name rather than an actual password value (as in the Listing 7 client-side example). When you use this approach, the referenced class must implement the javax.security.auth.callback.CallbackHandler
interface, and it will be called by the WSIT code when it needs access to the password for the secret key. You can also use this same technique of specifying a class name rather than a password value for the storepass
values.
Listing 8. Signing and encrypting policy with WSIT server-side extensions
<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsu=
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
wsu:Id="SignEncr">
<wsp:ExactlyOne>
<wsp:All>
<sp:AsymmetricBinding xmlns:sp=
"http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:Policy>
...
</wsp:Policy>
</sp:AsymmetricBinding>
<sp:SignedParts
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<sp:Body/>
</sp:SignedParts>
<sp:EncryptedParts
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<sp:Body/>
</sp:EncryptedParts> <wsss:KeyStore alias="serverkey"
keypass="com.sosnoski.ws.library.metro.KeystoreAccess"
location="server.keystore" storepass="nosecret"
xmlns:wspp="http://java.sun.com/xml/ns/wsit/policy" wspp:visibility="private"
xmlns:wsss="http://schemas.sun.com/2006/03/wss/server"/>
<wsss:TrustStore location="server.keystore" storepass="nosecret"
xmlns:wspp="http://java.sun.com/xml/ns/wsit/policy" wspp:visibility="private"
xmlns:wsss="http://schemas.sun.com/2006/03/wss/server"/>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
Listing 9 shows the implementation of the CallbackHandler
interface used for this example:
Listing 9. Server key-store password callback code
public class KeystoreAccess implements CallbackHandler
{
public void handle(
Callback[] callbacks) throws IOException, UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
Callback callback = callbacks[i];
if (callback instanceof PasswordCallback) {
((PasswordCallback)callback).setPassword("serverpass".toCharArray());
} else {
throw new UnsupportedCallbackException(callback, "unknown callback");
}
}
}
}
Building and running the sample code
The signing and encrypting example uses the same build steps as the UsernameToken
example, except that you must change the build.properties file to use variant-name=signencr
(rather than the value username
for the UsernameToken
example).
Interoperability issue
If you try using the Axis2/Rampart client with the Metro/WSIT server (or vice versa) you may run into a problem when the client tries to add a book with a duplicate International Standard Book Number (ISBN). In this case the service returns a Fault, rather than a normal SOAP response message. The Axis2/Rampart 1.5.x releases correctly perform the usual signature and encryption handling required by the WSDL in this case, but Metro/WSIT 1.5 does not, resulting in a failure on the client. This is an error in the WSIT code, which should be corrected for the next Metro release.
If you run the test with an earlier version of Axis2/Rampart, you probably won't see any problems — because Rampart had the same bug up until the Rampart 1.5 release.
Next stop on the Metro
Metro's WSIT support for WS-SecurityPolicy allows both direct configuration of parameters such as usernames and passwords (including key store and private-key passwords) and the use of callbacks to get these values as needed. It also lets you choose between the servlet container's authorization handling and your own callback for verifying username and password combinations on the server. This flexibility allows Metro to meet the needs of many types of applications easily. It's also convenient that Metro comes with the WSIT/XWSS WS-Security support as integrated components, rather than a separate component (with its own release cycles, and generally incompatibilities between different versions of the core component) as with Axis2 and Rampart.
On the downside, information is sparse on using Metro/WSIT stand-alone and configuring it directly (as opposed to using it in combination with the NetBeans IDE and Glassfish application server). Many of the necessary options are documented only in blog postings or e-mail exchanges (seeResources).
The next Java Web services installment continues looking at Metro, this time with a focus on performance. See how Metro performance compares to Axis2, both for simple message exchanges and with WS-Security in use.
referenc from:
http://www.ibm.com/developerworks/java/library/j-jws10/index.html
Java Web services: WS-Security with Metro--referenc的更多相关文章
- [Web Service] Java Web Services Tutorial
两种主要的java web services api: JAX-WS 和JAX-RS. Java web service application 之间通过WSDL来交互. 有两种方法来书写java w ...
- Java Web Services面试
Q. 应用集成方式有哪些? A. 应用可以采用以下方式集成: 1. 共享数据库 2. 批量文件传输 3. 远程过程调用(RPC) 4. 通过消息中间件来交换异步信息(MOM) Q. 应用集成可以采用的 ...
- 【转】Java Web Services面试问题集锦
Q. 应用集成方式有哪些? A. 应用可以采用以下方式集成: 1. 共享数据库 2. 批量文件传输 3. 远程过程调用(RPC) 4. 通过消息中间件来交换异步信息(MOM) Q. 应用集成可以采用的 ...
- Java Web Services (0) - Overview
前言第1章 Web服务快速入门 1.1 Web服务杂项 1.2 Web服务有什么好处 1.3 Web服务和面向服务的架构 1.4 Web服务简史 1.4.1 从DCE/RPC到XML-RPC 1.4. ...
- Java Web Services (1) - 第1章 Web服务快速入门
SCRIPTS_DIR=/Users/liuzhaofu/opus-dev/product/tools/devPRODUCT_DIR=/Users/liuzhaofu/opus-dev/product ...
- Java Web Services (2) - 第2章 启动日志分析
ZHAOFLIU-Mac:dev liuzhaofu$ ./start --seed########################################################## ...
- java Web Services搭建环境时遇到的各种问题,记录一下。 java.lang.OutOfMemoryError: PermGen space,org/apache/struts2/util/ObjectFactoryDestroyable
情况:在同一个,myEclipes 下加载俩个项目,一个seriver端,一个client端. 必备: myEclipes ,apache-tomcat-7.0.42,apache-tomcat ...
- Java与.NET 的Web Services相互调用
一:简介 本文介绍了Java与.NET开发的Web Services相互调用的技术.本文包括两个部分,第一部分介绍了如何用.NET做客户端调用Java写的Web Services,第二部分介绍了如何用 ...
- Java Web 学习路线
实际上,如果时间安排合理的话,大概需要六个月左右,有些基础好,自学能力强的朋友,甚至在四个月左右就开始找工作了.大三的时候,我萌生了放弃本专业的念头,断断续续学 Java Web 累计一年半左右,总算 ...
随机推荐
- HDU 2196-Computer(树形dp)
题意: 给出电脑网络连接树,求每个节点的为起点的最长距离 分析: 这道题开始状态想不出来,放了一段时间,后来注意到例题上有这道题,每个节点的最长距离可由父节点的最长距离,次长距离,和子节点的最长距离( ...
- 017QTP 描述性编程的使用方法
一.什么时候使用描述性编程 在测试过程中,有些界面元素是动态出现或动态变化的,在录制的时候并没有添加到对象库中 二.描述性编程的运行原理 用描述性编程编写的测试脚本在运行时,QTP会使用测试脚本中给出 ...
- mac远程连接 win8
首先 打开组策略 .windows8 下 按win+R 可以唤出运行,输入[gpedit.msc]按下 回车键 选择[计算机配置]>[管理模板]>[Windows组件]>[远程桌面服 ...
- Git管理命令
1.创建分支 git branch <分支名> 2.切换分支 git checkout <分支名> 创建并切换到该分支:git checkout -b <分支名> ...
- 取小数点后三位的方法(js)
使用js取小数点后三位的方法,我觉得这个方法最好 Math.round(num*100)/100 还有其他方法: http://hi.baidu.com/yansueh/item/f026d8d759 ...
- linux操作系统cp命令
- Obective-C之宏定义
优(dan)美(teng)的前奏 宏定义这个东东,估计大家在代码中应该天天用吧. 在我刚刚做的一个项目中,各种往代码里码“#define”这种预处理指令. 什么动画时长啊,cell高度啊,cell的个 ...
- 8.1.C++ AMP简介
C++ AMP是专为设计支持C++的异构并行模型. 全程是: Accelerator Massive Parallelism 下面是一个Vector C++ AMP的代码,通过这段代码来解释C++ A ...
- java@ LinkedList 学习
package abc.com; import java.util.LinkedList; public class TestLinkedList { static void prt(Object o ...
- SGU131 - Hardwood floor(状态压缩DP)
题目大意 给定一个N*M大小的矩形,要求你用1*2和2*2(缺个角)的砖块把矩形铺满(不能重叠),问总共有多少种铺法? 题解 受POJ2411的影响,怎么都没想到3,4,5,6这几种情况该怎么放置,看 ...