I am trying to call a Webservice using jax-ws. While calling the WS I faced below error,
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<S:Fault xmlns:ns4="http://www.w3.org/2003/05/soap-envelope">
<faultcode>S:Server</faultcode>
<faultstring>Unable to add security token for identity, token uri =http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken</faultstring>
<faultactor/>
</S:Fault>
</S:Body>
</S:Envelope>
I searched for this error and found out that it expects userid/password in header. So to add the user credentials in header I have implemented custom handler.
import java.util.Set;
import java.util.TreeSet;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFactory;
import javax.xml.soap.SOAPHeader;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
public class UsrSecHandler implements SOAPHandler<SOAPMessageContext>
{
private static final String AUTH_NS = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
private static final String AUTH_PREFIX="wsse";
private String pwd;
private String userName = null;
private SOAPFactory mSoapFactory = null;
public UsrSecHandler(String username, String password) {
this.userName = username;
this.pwd = password;
}
@Override
public boolean handleMessage(SOAPMessageContext context)
{
Boolean outboundProperty = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (outboundProperty.booleanValue())
{
try
{
SOAPEnvelope envelope = context.getMessage().getSOAPPart().getEnvelope();
if (mSoapFactory == null)
{
mSoapFactory = SOAPFactory.newInstance();
}
SOAPElement wsSecHeaderElm, userNameTokenElm, userNameElm, passwdElm;
// WSSecurity <Security> header
wsSecHeaderElm = mSoapFactory.createElement("Security",AUTH_PREFIX,AUTH_NS);
userNameTokenElm = mSoapFactory.createElement("UsernameToken",AUTH_PREFIX,AUTH_NS);
userNameElm = mSoapFactory.createElement("Username",AUTH_PREFIX,AUTH_NS);
passwdElm = mSoapFactory.createElement("Password",AUTH_PREFIX,AUTH_NS);
userNameElm.addTextNode(this.userName);
passwdElm.addTextNode(this.pwd);
userNameTokenElm.addChildElement(userNameElm);
userNameTokenElm.addChildElement(passwdElm);
// add child elements to the root element
wsSecHeaderElm.addChildElement(userNameTokenElm);
// create SOAPHeader instance for SOAP envelope
SOAPHeader header = envelope.getHeader();
if (header == null) {
header = envelope.addHeader();
}
header.addChildElement(wsSecHeaderElm);
}
catch (SOAPException e)
{
e.printStackTrace();
}catch (Exception e){
e.printStackTrace();
}
}
return true;
}
@Override
public Set<QName> getHeaders()
{
return new TreeSet<QName>();
}
@Override
public boolean handleFault(SOAPMessageContext context)
{
return false;
}
@Override
public void close(MessageContext context)
{
//
}
}
I am using below code to plug the custom handler and call the WS.
ManagementServices service = new ManagementServices(webServiceUrl);
Impl_ManagementServices port = service.getManagementServices();
final Binding binding = ((BindingProvider) port).getBinding();
List<Handler> handlerList = binding.getHandlerChain();
handlerList.add(new UsrSecHandler(LOGIN, PASS));
binding.setHandlerChain(handlerList);
port.callingManageService(some_input);
After adding Handler, The code worked fine on Eclipse when I run it standalone. But when I deployed the same code on Weblogic It is still throwing the same error. In the logs I am printing the Envelope. When I am using the same exact envelope(copy/paste) in Soap UI again it is working fine. But some how it is not working when deployed on Weblogic.
Below is The policy defined.
<wsp:Policy wssutil:Id="UsernameToken">
<ns1:SupportingTokens xmlns:ns1="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200512">
<wsp:Policy>
<ns1:UsernameToken ns1:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200512/IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<ns1:WssUsernameToken10/>
</wsp:Policy>
</ns1:UsernameToken>
</wsp:Policy>
</ns1:SupportingTokens>
</wsp:Policy>
client : WebLogic Server Version: 14.1.1.0.0
Server/host : WebLogic Server Version: 10.3.6.0
Not able to understand this behavior, Could any one please help me out with this ?
Finally resolved this.
Before
ManagementServices service = new ManagementServices(webServiceUrl);
Impl_ManagementServices port = service.getManagementServices();
final Binding binding = ((BindingProvider) port).getBinding();
List<Handler> handlerList = binding.getHandlerChain();
handlerList.add(new UsrSecHandler(LOGIN, PASS));
binding.setHandlerChain(handlerList);
port.callingManageService(some_input);
Now (changed/working code)
import weblogic.wsee.security.unt.ClientUNTCredentialProvider;
import weblogic.xml.crypto.wss.WSSecurityContext;
import weblogic.xml.crypto.wss.provider.CredentialProvider;
import javax.xml.ws.BindingProvider;
ManagementServices service = new ManagementServices(webServiceUrl);
Impl_ManagementServices port = service.getManagementServices();
List<CredentialProvider> credProviders = new ArrayList<CredentialProvider>();
CredentialProvider cp = new ClientUNTCredentialProvider("username".getBytes(), "password".getBytes());
credProviders.add(cp);
Map<String, Object> requestContext = ((BindingProvider) port).getRequestContext();
requestContext.put(WSSecurityContext.CREDENTIAL_PROVIDER_LIST, credProviders);
port.callingManageService(some_input);