Just one amendment here in my speculation about the fault cause.
I wrote this in the previous thread,
"but I dont know why I am getting this error pwd == null but a
password is needed at pwcb.setPassword(passwd);"
Now, i dont think this fault is coming from here
pwcb.setPassword(passwd);
as I have tested it by removing the following code to be sure about
the fault
if (!pwcb.getPassword().equals(passwd)) {
LOG.debug("wrong password");
throw new IOException("wrong password");
} else {
LOG.debug("I am setting the password
here ::::" + passwd);
pwcb.setPassword(passwd);
}
from ServerPasswordHandler and I still have the same fault error in
the response.
Please correct me if I am wrong somewhere. I am not sure where this
fault come from?
Thank you.
Best Regards,
Rahul
On Mon, Jul 27, 2009 at 12:07 AM, rahul.soa
<[email protected]> wrote:
Hello David/Devs,
Objective: trying to set web service security at serverside:
I am getting an error while accessing the secured webservice. The
soap fault I am receiving is below:
Response:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/
envelope/"><soap:Body><soap:Fault><faultcode>soap:Server</
faultcode><faultstring>pwd == null but a password is needed</
faultstring></soap:Fault></soap:Body></soap:Envelope>
Request:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/
envelope/"><soap:Header><wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd
" soap:mustUnderstand="1"><wsse:UsernameToken xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd
" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd
" wsu:Id="UsernameToken-32620541"><wsse:Username xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd
">system</wsse:Username><wsse:Password xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd
" Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText
">manager</wsse:Password></wsse:UsernameToken></wsse:Security></
soap:Header><soap:Body><add xmlns="http://jws.samples.geronimo.apache.org
"><value1>2</value1><value2>2</value2></add></soap:Body></
soap:Envelope>
How I am trying to do is,
1. At, server side (in the doPublish method of CXFEndpoint), I am
setting the WSS4JIn/OutInterceptor property for user token (please
note: this is not generic code at this moment)
protected void doPublish(String baseAddress) {
// XXX: assume port 8080 by default since we don't know the
actual port
// at startup
String address = (baseAddress == null) ? "http://localhost:8080
"
: baseAddress;
JaxWsServerFactoryBean svrFactory = new
GeronimoJaxWsServerFactoryBean();
svrFactory.setBus(bus);
svrFactory.setAddress(address + this.portInfo.getLocation());
svrFactory.setServiceFactory(serviceFactory);
svrFactory.setStart(false);
svrFactory.setServiceBean(implementor);
if
(HTTPBinding.HTTP_BINDING.equals(implInfo.getBindingType())) {
svrFactory.setTransportId("http://cxf.apache.org/bindings/xformat
");
}
// to receive the incoming username/password in soap request
Map inProps = new HashMap();
inProps.put(WSHandlerConstants.ACTION,
WSHandlerConstants.USERNAME_TOKEN);
inProps.put(WSHandlerConstants.PASSWORD_TYPE,
WSConstants.PW_TEXT);
inProps.put(WSHandlerConstants.USER, "system");
inProps.put(WSHandlerConstants.PW_CALLBACK_REF,
new ServerPasswordHandler());
server = svrFactory.create();
// to receive the secure header
WSS4JInInterceptor wssIn = new WSS4JInInterceptor(inProps);
// to send the secure soap header
WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(inProps);
init();
org.apache.cxf.endpoint.Endpoint endpoint = getEndpoint();
endpoint.getInInterceptors().add(wssIn);
endpoint.getInInterceptors().add(
new
org.apache.cxf.binding.soap.saaj.SAAJInInterceptor());
endpoint.getOutInterceptors().add(wssOut);
endpoint.getOutInterceptors().add(
new
org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor());
LOG.debug("So far set the interceptor");
//
if (getBinding() instanceof SOAPBinding
&& this.portInfo.isMTOMEnabled() != null) {
((SOAPBinding) getBinding()).setMTOMEnabled(this.portInfo
.isMTOMEnabled());
}
server.start();
LOG.debug("Invoked");
}
I am setting up the login authentication and setting the password in
the Server Handler, like following:
public class ServerPasswordHandler implements CallbackHandler {
private static final Logger LOG = LoggerFactory
.getLogger(ServerPasswordHandler.class);
public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
WSPasswordCallback pwcb = (WSPasswordCallback)
callbacks[i];
if (pwcb.getUsage() ==
WSPasswordCallback.USERNAME_TOKEN_UNKNOWN) {
LOG.debug("I am inside the ServerPasswordHandler");
String username = pwcb.getIdentifier();
String passwd = pwcb.getPassword();
LoginContext context = null;
try {
// Login authentication goes here
// use the existing security realm for the
moment for testing
context = ContextManager.login("geronimo-admin",
new
UsernamePasswordCallbackHandler(username,
passwd));
// ContextManager.login(realm, callbackHandler,
// configuration)
context.login();
LOG.debug("login is successful");
} catch (LoginException e) {
LOG.debug("login failed");
throw new IOException("Unable to verify " +
username
+ " and " + passwd);
}
//TODO: what to do with subject
Subject subject = context.getSubject();
ContextManager.setCallers(subject, subject);
if (!pwcb.getPassword().equals(passwd)) {
LOG.debug("wrong password");
throw new IOException("wrong password");
} else {
LOG.debug("I am setting the password
here ::::"
+ passwd);
pwcb.setPassword(passwd);
}
}
}
}
}
In the traces, I can see the password value is "manager" which is
sent by client
I am setting the password here ::::manager
but I dont know why I am getting this error pwd == null but a
password is needed at pwcb.setPassword(passwd);
Login authentication goes sucessful when the client provides the
correct username and password (which are "system and "manager"
respectively). and goes unsuccessful otherwise.
The full trace from the geronimo.log is attached here: (there are
some debug statement to see the traces )
2009-07-27 01:26:17,809 DEBUG [JAXWSServiceReference] Initializing
service with: file:/home/rahul/new_workspace1/GerominoWebClient/WEB-
INF/wsdl/CalculatorService.wsdl {http://jws.samples.geronimo.apache.org
}Calculator
2009-07-27 01:26:18,031 DEBUG [PortMethodInterceptor] Set address
property: http://localhost:8080/GerominoWeb/calculator
2009-07-27 01:26:18,031 DEBUG [CXFPortMethodInterceptor] Username
and password sent by Clients are : system manager
2009-07-27 01:26:18,126 DEBUG [CXFPasswordHandler] I HAVE SET THE
VALUES system and manager
2009-07-27 01:26:18,142 DEBUG [ServerPasswordHandler] I am inside
the ServerPasswordHandler
2009-07-27 01:26:18,143 DEBUG [UsernamePasswordCallbackHandler] WHAT
I GOT HERE: system and manager
2009-07-27 01:26:18,143 DEBUG [UsernamePasswordCallbackHandler]
Username set to: system
2009-07-27 01:26:18,143 DEBUG [UsernamePasswordCallbackHandler]
password set to: manager
2009-07-27 01:26:18,144 DEBUG [UsernamePasswordCallbackHandler] WHAT
I GOT HERE: system and manager
2009-07-27 01:26:18,144 DEBUG [UsernamePasswordCallbackHandler]
Username set to: system
2009-07-27 01:26:18,144 DEBUG [UsernamePasswordCallbackHandler]
password set to: manager
2009-07-27 01:26:18,144 DEBUG [ServerPasswordHandler] login is
successful
2009-07-27 01:26:18,145 DEBUG [ServerPasswordHandler] I am setting
the password here ::::manager
2009-07-27 01:26:18,313 INFO [PhaseInterceptorChain] Interceptor
has thrown exception, unwinding now pwd == null but a password is
needed
2009-07-27 01:26:18,376 ERROR [log] /jaxws-calculator/calculator
javax.xml.ws.soap.SOAPFaultException: pwd == null but a password is
needed
at
org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:
145)
at $Proxy67.add(Unknown Source)
at CalculatorServlet.doGet(CalculatorServlet.java:42)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:693)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:806)
at
org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:521)
at
org
.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:
435)
at
org
.eclipse
.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:118)
at
org
.eclipse
.jetty.server.session.SessionHandler.handle(SessionHandler.java:179)
at
org
.eclipse
.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:928)
at
org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:
370)
at
org
.eclipse
.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:862)
at
org
.apache
.geronimo
.jetty7
.handler.GeronimoWebAppContext.doScope(GeronimoWebAppContext.java:107)
at
org
.eclipse
.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:116)
at
org
.eclipse
.jetty
.server
.handler
.ContextHandlerCollection.handle(ContextHandlerCollection.java:243)
at
org
.eclipse
.jetty
.server.handler.HandlerCollection.handle(HandlerCollection.java:126)
at
org
.eclipse
.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:115)
at org.eclipse.jetty.server.Server.handle(Server.java:337)
at
org
.eclipse
.jetty.server.HttpConnection.handleRequest(HttpConnection.java:561)
at org.eclipse.jetty.server.HttpConnection
$RequestHandler.headerComplete(HttpConnection.java:943)
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:
530)
at
org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:203)
at
org.eclipse.jetty.server.HttpConnection.handle(HttpConnection.java:
414)
at
org
.eclipse
.jetty.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:
437)
at org.apache.geronimo.pool.ThreadPool$1.run(ThreadPool.java:214)
at org.apache.geronimo.pool.ThreadPool
$ContextClassLoaderRunnable.run(ThreadPool.java:344)
at java.util.concurrent.ThreadPoolExecutor
$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor
$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
Caused by: org.apache.cxf.binding.soap.SoapFault: pwd == null but a
password is needed
at
org
.apache
.cxf
.binding
.soap
.interceptor
.Soap11FaultInInterceptor
.unmarshalFault(Soap11FaultInInterceptor.java:75)
at
org
.apache
.cxf
.binding
.soap
.interceptor
.Soap11FaultInInterceptor
.handleMessage(Soap11FaultInInterceptor.java:46)
at
org
.apache
.cxf
.binding
.soap
.interceptor
.Soap11FaultInInterceptor
.handleMessage(Soap11FaultInInterceptor.java:35)
at
org
.apache
.cxf
.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:
226)
at
org
.apache
.cxf
.interceptor
.AbstractFaultChainInitiatorObserver
.onMessage(AbstractFaultChainInitiatorObserver.java:96)
at
org
.apache
.cxf
.binding
.soap
.interceptor
.CheckFaultInterceptor.handleMessage(CheckFaultInterceptor.java:69)
at
org
.apache
.cxf
.binding
.soap
.interceptor
.CheckFaultInterceptor.handleMessage(CheckFaultInterceptor.java:34)
at
org
.apache
.cxf
.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:
226)
at org.apache.cxf.endpoint.ClientImpl.onMessage(ClientImpl.java:
641)
at org.apache.cxf.transport.http.HTTPConduit
$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:2102)
at org.apache.cxf.transport.http.HTTPConduit
$WrappedOutputStream.handleResponse(HTTPConduit.java:1980)
at org.apache.cxf.transport.http.HTTPConduit
$WrappedOutputStream.close(HTTPConduit.java:1905)
at
org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:
66)
at
org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:600)
at org.apache.cxf.interceptor.MessageSenderInterceptor
$
MessageSenderEndingInterceptor
.handleMessage(MessageSenderInterceptor.java:62)
at
org
.apache
.cxf
.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:
226)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:469)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:299)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:251)
at
org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:73)
at
org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:
124)
... 28 more
Can you please let me know or correct me, why this is happening?, I
think if password is set correctly in the pwcb.setPassword(passwd);
then client should be able to access the secure web service. I am
getting the correct password "manager" (as seen in the logs) and
setting the same but I dont know why I am getting this fault.
Second thing is, I am not sure what to do with subject?
Am I missing something in the above code? Please correct me and help
me in this.
Many Thanks in advance for your response.
Regards,
Rahul