Hi, We are facing some issues while trying to run STS example shared with CXF archive.
Use case is: We are running the service which comes with CXF Sample code and trying to write the client with standalone java program. We are using the CXF WS- Dispatch API to send the request. 1. If we run the sample client no issues and get the response. 2. If we are trying with custom code getting following exception(HTTP response '307: Temporary Redirect' when communicating with http://www.w3.org/2005/08/addressing) from sts server After this exception I am pasting the complete code we have written. Please let us know if we are doing something wrong or over engineering. Feb 14, 2014 6:08:18 PM org.apache.cxf.phase.PhaseInterceptorChain doDefaultLogging WARNING: Interceptor for {http://apache.org/hello_world_soap_http}SOAPService#{http://apache.org/hello_world_soap_http}greetMe has thrown exception, unwinding now org.apache.cxf.ws.policy.PolicyException: These policy alternatives can not be satisfied: {http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702}EncryptedParts: {http://schemas.xmlsoap.org/soap/envelope/}Body not ENCRYPTED {http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702}SignedParts: {http://schemas.xmlsoap.org/soap/envelope/}Body not SIGNED at org.apache.cxf.ws.policy.AssertionInfoMap.checkEffectivePolicy(AssertionInfoMap.java:179) at org.apache.cxf.ws.policy.PolicyVerificationInInterceptor.handle(PolicyVerificationInInterceptor.java:101) at org.apache.cxf.ws.policy.AbstractPolicyInterceptor.handleMessage(AbstractPolicyInterceptor.java:44) at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:272) at org.apache.cxf.phase.PhaseInterceptorChain.resume(PhaseInterceptorChain.java:242) at org.apache.cxf.ws.addressing.impl.InternalContextUtils$1.run(InternalContextUtils.java:265) at org.apache.cxf.workqueue.AutomaticWorkQueueImpl$3.run(AutomaticWorkQueueImpl.java:428) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) at org.apache.cxf.workqueue.AutomaticWorkQueueImpl$AWQThreadFactory$1.run(AutomaticWorkQueueImpl.java:353) at java.lang.Thread.run(Thread.java:662) Feb 14, 2014 6:08:18 PM org.apache.cxf.services.SOAPService.SoapPort.Greeter INFO: Outbound Message --------------------------- ID: 1 Address: http://www.w3.org/2005/08/addressing Response-Code: 500 Encoding: UTF-8 Http-Method: POST Content-Type: text/xml Headers: {Accept=[*/*]} Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><soap:Fault><faultcode>soap:Server</faultcode><faultstring>These policy alternatives can not be satisfied: {http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702}EncryptedParts: {http://schemas.xmlsoap.org/soap/envelope/}Body not ENCRYPTED {http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702}SignedParts: {http://schemas.xmlsoap.org/soap/envelope/}Body not SIGNED</faultstring></soap:Fault></soap:Body></soap:Envelope> -------------------------------------- Feb 14, 2014 6:08:19 PM org.apache.cxf.phase.PhaseInterceptorChain doDefaultLogging WARNING: Interceptor for {http://apache.org/hello_world_soap_http}SOAPService#{http://apache.org/hello_world_soap_http}greetMe has thrown exception, unwinding now org.apache.cxf.interceptor.Fault: Could not send Message. at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:64) at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:272) at org.apache.cxf.interceptor.AbstractFaultChainInitiatorObserver.onMessage(AbstractFaultChainInitiatorObserver.java:113) at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:333) at org.apache.cxf.phase.PhaseInterceptorChain.resume(PhaseInterceptorChain.java:242) at org.apache.cxf.ws.addressing.impl.InternalContextUtils$1.run(InternalContextUtils.java:265) at org.apache.cxf.workqueue.AutomaticWorkQueueImpl$3.run(AutomaticWorkQueueImpl.java:428) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) at org.apache.cxf.workqueue.AutomaticWorkQueueImpl$AWQThreadFactory$1.run(AutomaticWorkQueueImpl.java:353) at java.lang.Thread.run(Thread.java:662) Caused by: org.apache.cxf.transport.http.HTTPException: HTTP response '307: Temporary Redirect' when communicating with http://www.w3.org/2005/08/addressing at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1567) at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1503) at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1310) at org.apache.cxf.io.CacheAndWriteOutputStream.postClose(CacheAndWriteOutputStream.java:50) at org.apache.cxf.io.CachedOutputStream.close(CachedOutputStream.java:223) at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56) at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:628) at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62) ... 10 more Following is the complete code TestCXFSTS.java package com.cxf.sample; import static org.apache.cxf.ws.addressing.JAXWSAConstants.CLIENT_ADDRESSING_PROPERTIES; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.xml.namespace.QName; import javax.xml.soap.MessageFactory; import javax.xml.soap.SOAPBody; import javax.xml.soap.SOAPConstants; import javax.xml.soap.SOAPElement; import javax.xml.soap.SOAPEnvelope; import javax.xml.soap.SOAPMessage; import javax.xml.soap.SOAPPart; import javax.xml.ws.Dispatch; import javax.xml.ws.soap.SOAPBinding; import org.apache.cxf.Bus; import org.apache.cxf.BusFactory; import org.apache.cxf.endpoint.Client; import org.apache.cxf.feature.AbstractFeature; import org.apache.cxf.feature.LoggingFeature; import org.apache.cxf.jaxws.DispatchImpl; import org.apache.cxf.ws.addressing.AddressingProperties; import org.apache.cxf.ws.addressing.AttributedURIType; import org.apache.cxf.ws.addressing.EndpointReferenceType; import org.apache.cxf.ws.addressing.MetadataType; import org.apache.cxf.ws.addressing.ObjectFactory; import org.apache.cxf.ws.addressing.ReferenceParametersType; import org.apache.cxf.ws.addressing.RelatesToType; import org.apache.cxf.ws.addressing.WSAddressingFeature; import org.apache.cxf.ws.addressing.impl.AddressingPropertiesImpl; import org.apache.cxf.ws.policy.PolicyConstants; import org.apache.cxf.ws.policy.WSPolicyFeature; import org.apache.cxf.ws.security.SecurityConstants; import org.apache.cxf.ws.security.trust.STSClient; import org.apache.neethi.Policy; public class TestCXFSTS { private static final ObjectFactory WSA_OBJECT_FACTORY = new ObjectFactory(); /** * @param args * @throws Exception */ public static void main(String[] args) throws Exception { testService1(); } private static void testService1() throws Exception { Dispatch<SOAPMessage> dispatch = CXFUtils.getDispatch( SOAPBinding.SOAP11HTTP_BINDING, "http://127.0.0.1:9001/SoapContext/SoapPort"); Client disPatchClient = ((DispatchImpl<SOAPMessage>) dispatch).getClient(); //Engage the policy after parsing with neethi library Policy wsaPolicy = PolicyHelper.parsePolicy(disPatchClient, "c://wsa-policy.xml"); dispatch.getRequestContext().put(PolicyConstants.POLICY_OVERRIDE, wsaPolicy); //Add the client addressing properties dispatch.getRequestContext().put(CLIENT_ADDRESSING_PROPERTIES,createMaps()); //Build the bus object Bus bus = BusFactory.getDefaultBus(); List<AbstractFeature> features = new ArrayList<AbstractFeature>(); features.add(new WSAddressingFeature()); features.add(new WSPolicyFeature()); features.add(new LoggingFeature()); for(AbstractFeature feature : features) { feature.initialize(bus); } //Create the STSClient and set the properties STSClient stsClient = new STSClient(bus); stsClient.setServiceQName(new QName("http://docs.oasis-open.org/ws-sx/ws-trust/200512/","SecurityTokenService")); stsClient.setEndpointQName(new QName("http://docs.oasis-open.org/ws-sx/ws-trust/200512/","UT_Port")); stsClient.setWsdlLocation("http://localhost:8080/SecurityTokenService/UT?wsdl"); stsClient.setEnableAppliesTo(false); Map<String, Object> stsprop = new HashMap<String, Object>() ; stsprop.put("ws-security.username","alice"); stsprop.put("ws-security.callback-handler","com.cxf.sample.ClientCallbackHandler"); stsprop.put("ws-security.encryption.properties","clientKeystore.properties"); stsprop.put("ws-security.encryption.username","mystskey"); stsprop.put("ws-security.sts.token.username","myclientkey"); stsprop.put("ws-security.sts.token.properties","clientKeystore.properties"); stsprop.put("ws-security.sts.token.usecert","true"); stsprop.put(SecurityConstants.IS_BSP_COMPLIANT, "false"); stsClient.setProperties(stsprop); disPatchClient.getRequestContext().put("ws-security.sts.client", stsClient ); Map<String,Object> stsmap = setSTSMaps(); disPatchClient.getRequestContext().putAll(stsmap); MessageFactory mf = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL); SOAPMessage request = mf.createMessage(); SOAPPart part = request.getSOAPPart(); // Obtain the SOAPEnvelope and header and body elements. SOAPEnvelope env = part.getEnvelope(); SOAPBody body = env.getBody(); // Construct the message payload. SOAPElement operation = body.addChildElement("greetMe", "tns", "http://apache.org/hello_world_soap_http/types"); SOAPElement value = operation.addChildElement("requestType", "tns","http://apache.org/hello_world_soap_http/types"); value.addTextNode("Renu"); request.saveChanges(); SOAPMessage response = dispatch.invoke(request); System.out.println(response.getSOAPBody().getTextContent()); } private static Map<String,Object> setSTSMaps(){ Map<String,Object> stsmap = new HashMap<String, Object>(); stsmap.put("ws-security.signature.properties", "clientKeystore.properties"); stsmap.put("ws-security.signature.username", "myclientkey"); stsmap.put("ws-security.callback-handler", "com.cxf.sample.ClientCallbackHandler"); stsmap.put("ws-security.encryption.properties", "clientKeystore.properties"); stsmap.put("ws-security.encryption.username", "myservicekey"); return stsmap; } private static AddressingProperties createMaps() { // get Message Addressing Properties instance AddressingProperties maps = new AddressingPropertiesImpl(); // set MessageID property AttributedURIType messageID = WSA_OBJECT_FACTORY.createAttributedURIType(); AttributedURIType action = WSA_OBJECT_FACTORY.createAttributedURIType(); messageID.setValue("urn:uuid:" + System.currentTimeMillis()); AttributedURIType to = WSA_OBJECT_FACTORY.createAttributedURIType(); to.setValue("http://www.w3.org/2005/08/addressing"); EndpointReferenceType toRefType = WSA_OBJECT_FACTORY.createEndpointReferenceType(); toRefType.setAddress(to); EndpointReferenceType fault = WSA_OBJECT_FACTORY.createEndpointReferenceType(); AttributedURIType faultTo = WSA_OBJECT_FACTORY.createAttributedURIType(); faultTo.setValue("http://www.w3.org/2005/08/addressing"); fault.setAddress(faultTo); EndpointReferenceType reply = WSA_OBJECT_FACTORY.createEndpointReferenceType(); AttributedURIType replyTo = WSA_OBJECT_FACTORY.createAttributedURIType(); replyTo.setValue("http://www.w3.org/2005/08/addressing"); reply.setAddress(replyTo); EndpointReferenceType relates = WSA_OBJECT_FACTORY.createEndpointReferenceType(); AttributedURIType relatesTo = WSA_OBJECT_FACTORY.createAttributedURIType(); relatesTo.setValue("http://www.w3.org/2005/08/addressing"); relates.setAddress(relatesTo); action.setValue("http://www.w3.org/2005/08/addressing"); maps.setTo(toRefType); maps.setTo(to); maps.setAction(action); maps.setMessageID(messageID); maps.setFaultTo(fault); RelatesToType rel = WSA_OBJECT_FACTORY.createRelatesToType(); rel.setRelationshipType("http://www.w3.org/2005/08/addressing"); rel.setValue("http://www.w3.org/2005/08/addressing"); maps.setRelatesTo(rel ); maps.setReplyTo(reply); ReferenceParametersType value = WSA_OBJECT_FACTORY.createReferenceParametersType(); value.getAny().add("http://www.w3.org/2005/08/addressing"); MetadataType value1 = WSA_OBJECT_FACTORY.createMetadataType(); value1.getAny().add("http://www.w3.org/2005/08/addressing"); return maps; } } *************************************************************************************************************************************************************** ClientCallbackHandler.java /** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.cxf.sample; import java.io.IOException; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; import org.apache.ws.security.WSPasswordCallback; public class ClientCallbackHandler implements CallbackHandler { public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (int i = 0; i < callbacks.length; i++) { if (callbacks[i] instanceof WSPasswordCallback) { WSPasswordCallback pc = (WSPasswordCallback) callbacks[i]; if (pc.getUsage() == WSPasswordCallback.DECRYPT || pc.getUsage() == WSPasswordCallback.SIGNATURE) { if ("myclientkey".equals(pc.getIdentifier())) { pc.setPassword("ckpass"); } } else if (pc.getUsage() == WSPasswordCallback.USERNAME_TOKEN) { if ("alice".equals(pc.getIdentifier())) { pc.setPassword("clarinet"); break; } else if ("bob".equals(pc.getIdentifier())) { pc.setPassword("trombone"); break; } } } } } } PolicyHelper.java package com.cxf.sample; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.apache.cxf.endpoint.Client; import org.apache.cxf.helpers.DOMUtils; import org.apache.cxf.helpers.DOMUtils.NullResolver; import org.apache.neethi.Policy; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; public class PolicyHelper { private PolicyHelper() { } public static Policy parsePolicy(Client msg, String policyPath) { try { // 1. Load policy as DOM InputStream is = new FileInputStream("C:\\wsa-policy.xml"); //com.pega.apache.neethi.Policy stsPolicyObject= com.pega.apache.neethi.PolicyEngine.getPolicy(readXml(is).getDocumentElement()); //Element policyElement = readXml(is).getDocumentElement(); Document readXml = DOMUtils.readXml(is); Node firstChild = readXml.getFirstChild(); Element policyElementA = readXml.getDocumentElement(); NodeList childNodes = readXml.getChildNodes(); // 2. Parse policy org.apache.cxf.ws.policy.PolicyBuilder builder = msg.getBus() .getExtension(org.apache.cxf.ws.policy.PolicyBuilder.class); return builder.getPolicy(policyElementA); } catch (Exception e) { throw new RuntimeException("Cannot parse policy: " + e.getMessage(), e); } } public static Document readXml(InputStream inputStream) throws SAXException, IOException, ParserConfigurationException { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setValidating(false); dbf.setIgnoringComments(false); dbf.setIgnoringElementContentWhitespace(true); dbf.setNamespaceAware(true); // dbf.setCoalescing(true); // dbf.setExpandEntityReferences(true); DocumentBuilder db = null; db = dbf.newDocumentBuilder(); db.setEntityResolver(new NullResolver()); return db.parse(inputStream); } } Regards, Praveen
