users@jax-rpc.java.net

Re: Callback Handler only being called once.

From: David Sharp <dsharp02_at_gmail.com>
Date: Wed, 28 Sep 2005 10:20:22 -0500

My apologies for the length of this reply. I have tried to be as complete as
possible without flooding everyone with useless information.

Using the same password was a mistake in my example. Here are the contents
of my security configuration file.

===
<xwss:JAXRPCSecurity xmlns:xwss="http://java.sun.com/xml/ns/xwss/config">
<xwss:Service>
<xwss:SecurityConfiguration dumpMessages="false">
<xwss:UsernameToken digestPassword="false" useNonce="true"/>
</xwss:SecurityConfiguration>
</xwss:Service>
<xwss:SecurityEnvironmentHandler>
claimnet.webservice.client.PasswordHandler
</xwss:SecurityEnvironmentHandler>
</xwss:JAXRPCSecurity>
===

Here is my CallbackHandler class:
===
package claimnet.webservice.client;
import com.sun.xml.wss.impl.callback.PasswordCallback;
import com.sun.xml.wss.impl.callback.UsernameCallback;
import java.io.IOException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import claimnet.webservice.client.ServicePort;

public class PasswordHandler implements CallbackHandler
{
public void handle(Callback[] callbacks) throws
IOException, UnsupportedCallbackException
{
for (int i = 0; i < callbacks.length; ++i)
{
if (callbacks[i] instanceof UsernameCallback)
{
UsernameCallback cb = (UsernameCallback)callbacks[i];
String user = ServicePort.getUsername();
System.err.println("user = " + user);
cb.setUsername(
ServicePort.getUsername()
);
}
else if (callbacks[i] instanceof PasswordCallback)
{
PasswordCallback cb = (PasswordCallback)callbacks[i];
//cb.setPassword("testpw");
String password = ServicePort.getPassword();
System.err.println("password = " + password);
cb.setPassword(
ServicePort.getPassword()
);
}
else
{
String msg = "Only plain text username and passwords are " +
"supported by this client.";
throw new UnsupportedCallbackException(callbacks[i], msg);
}
}
}
}
===

As you can see I'm doing prints to System.err each time the callback is
invoked, and I'm only seeing the invocation on the first invocation, and not
on any subsequent invocations.

The client is a jsp page that accepts the web service URL, the username and
password from the user's web browser. I've also been able to duplicate the
issue with a command line program where I change the password inside the
code. Here is the jsp that is the web service client:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<%@ page import="claimnet.webservice.client.*" %>
<%@ page import="java.io.*" %>
<%!
private ServiceTest testPort = new ServiceTest();
class TestCallback implements ServiceTestCallback
{
public void setOut(java.io.Writer out)
{
myOut = out;
}
public void startTest()
throws java.io.IOException
{
mySuccess = true;
myOut.write(myTestcase + "\n");
myOut.flush();
}

public void writeStatus()
throws java.io.IOException
{
if (mySuccess)
{
myOut.write("Test Succeeded\n" + "\n");
myOut.flush();
}
else
{
myOut.write("Test Failed\n" + "\n");
myOut.flush();
}
}
public boolean isSuccess()
{
return mySuccess;
}

public TestCallback(String testcase)
{
myTestcase = testcase;
}

public void addResult(String testName, boolean success, ServiceException e)
{
try
{
myOut.write("\t" + testName + "() ");
for (int i=0; i< 30 - testName.length(); ++i)
{
myOut.write(".");
}
if ( myExpectedFailures.containsKey(testName) )
{
success = !success;
if (success)
{
int expectedCode
= ((Integer) myExpectedFailures.get(testName)).intValue();
if (e.getError().getCode() == expectedCode)
{
myOut.write(" failed as expected\n");
}
else
{
myOut.write(" failed with an unexpected error code\n"
+ "\t" + e.getError().getCode() + ": " + e.getError().getExplanation() +
"\n"
);
success = false;
}
}
else
{
myOut.write(" passed unexpectedly\n");
}
}
else
{
if (success)
{
myOut.write(" passed\n");
}
else
{
myOut.write(" failed\n");
}
}
myOut.flush();
mySuccess = mySuccess & success;
}
catch (java.io.IOException ioe)
{
e.printStackTrace(System.err);
}
}

public void expectFailure(String test,int code)
{
myExpectedFailures.put(test,new Integer(code));
}

public void expectSuccess(String test)
{
myExpectedFailures.remove(test);
}

private java.io.Writer myOut = null;
private java.util.TreeMap myExpectedFailures = new java.util.TreeMap();
private String myTestcase = null;
private boolean mySuccess = true;
}
class TestFailed extends Exception
{
public TestFailed(String message)
{
myMessage = message;
}

public String getMessage()
{
return myMessage;
}

private String myMessage = null;
}

%>
<html>
<head>
<title>ClaimNet Web Service Tester</title>
</head>
<body>
<form action="<%= request.getContextPath() + request.getServletPath() %>"
method="post">
Service URL:<input name="service_url" size="80" value="<%=
request.getParameter("service_url") %>"><br>
Service User:<input name="service_user" size="80" value="<%=
request.getParameter("service_user")%>"><br>
Service Password:<input name="service_password" size="80" value="<%=
request.getParameter("service_password")%>"><br>
<input type="submit" value="Test Service">
</form>
<pre>
<%
String url = request.getParameter("service_url");
String user = request.getParameter("service_user");
String password = request.getParameter("service_password");
out.write(" URL: " + url + "\n");
out.write(" User: " + user + "\n");
out.write("Password: " + password + "\n");
out.flush();

if ( (url != null) && !url.equals("") )
{

try
{
testPort.setEndpoint(url);
ServicePort.setUsername(user);
ServicePort.setPassword(password);

TestCallback cb = new TestCallback("Service Connectivity Test");
cb.setOut(out);
testPort.setCallback(cb);
cb.startTest();
testPort.servicePing("PING!");
cb.writeStatus();

}
catch (Exception e)
{
response.getOutputStream().print(e.getMessage());
}
}
%>
</pre>
</body>
</html>
===

Any help would be appreciated.

Thanks,
Dave

On 9/27/05, V B Kumar Jayanti <Vbkumar.Jayanti_at_sun.com> wrote:
>
> David Sharp wrote:
>
> > I am using JWSDP-1.5 and XWS to implement a web service. Everything
> > works fine so long as I only call a single web service. However, if I
> > call two different web services, things break because the
> > CallbackHandler is not called on every web service call. When I
> > switch try to call the second web service it is using the username and
> > password from the first service.
> >
> > The sequence of events goes something like this:
> >
> > ServicePort.setUsername("test"); //sets a static thread-local
> > variable to the proper username
> > ServicePort.setPassword("testpw"); //sets a static
> > thread-local variable to the proper password
> > //The callback handler will retrieve the username and password
> > from these static variables
> >
> > myStub = (ReceivershipServicePortType_Stub) new
> > ReceivershipService_Impl().getReceivershipPort();
> >
> > myStub._setProperty(
> com.sun.xml.rpc.client.StubBase.ENDPOINT_ADDRESS_PROPERTY,myEndpoint);
> >
> > ServicePing sp = new ServicePing();
> > sp.setEcho(echo);
> > ServicePingReturn rc = myStub.servicePing(sp);
> >
> > //now ping the second service
> > ServicePort.setUsername("test"); //sets a static thread-local
> > variable to the proper username
> > ServicePort.setPassword("testpw"); //sets a static
> > thread-local variable to the proper password
>
> Not sure if this is sample code or real code. If it is real code that
> you are using then please note that you have set the same username and
> password even while invoking the second endpoint.
>
> >
> >
> > myStub._setProperty(
> com.sun.xml.rpc.client.StubBase.ENDPOINT_ADDRESS_PROPERTY
> ,myOtherEndpoint);
> >
> > sp = new ServicePing();
> > sp.setEcho(echo);
> >
> > //call the new web service, should invoke the CallbackHandler,
> > but it does not. Instead it attempts to re-use the
> > //values from teh old webservice.
> > ServicePingReturn rc2 = myStub.servicePing(sp);
>
> If you have configured a <xwss:UsernameToken/> policy in the security
> configuration then the CallbackHandler should always be called on every
> invocation of the method servicePing.
>
>
> >
> >
> > // end-code
> >
> > How can I force the security framework to invoke the callback on every
> > webservice call?
> >
> > Thanks,
> > Dave
>
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jax-rpc.dev.java.net
> For additional commands, e-mail: users-help_at_jax-rpc.dev.java.net
>
>