Unable to invoke web service with security - java

I have crated a CXF JAXWS Service as below.
I have provided a custom UserNameToken validator and a callback handler.
But this is not working. It throws an error everytime.
<http:inbound-endpoint address="http://localhost:8080/HelloService" exchange-pattern="request-response">
<cxf:jaxws-service serviceClass="com.example.service.HelloServiceImpl" >
<cxf:ws-security>
<cxf:ws-config>
<cxf:property key="action" value="UsernameToken" />
</cxf:ws-config>
<cxf:ws-custom-validator >
<cxf:username-token-validator ref="customUsernameTokenValidator" />
</cxf:ws-custom-validator>
</cxf:ws-security>
<cxf:properties>
<spring:entry key="ws-security.ut.validator" value-ref="customUsernameTokenValidator" ></spring:entry>
<spring:entry key="ws-security.callback-handler" value-ref="myPasswordCallback" ></spring:entry>
</cxf:properties>
.....
.....
And a policy on my WSDL binding as below
<sp:SupportingTokens>
<wsp:Policy>
<sp:UsernameToken sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">
<wsp:Policy />
</sp:UsernameToken>
</wsp:Policy>
</sp:SupportingTokens>
I get the below error when I fire my request from SOAPUI with usernametoken and password.
2013-04-10 11:08:13,811 WARN [qtp1221956599-40 - /HelloService] logging.LogUtils (LogUtils.java:384) - Interceptor for {http://example.org/HelloService}ProductSOAPService#{http://example.org/HelloService}addCompany has thrown exception, unwinding now
org.apache.cxf.interceptor.Fault
at org.mule.module.cxf.MuleInvoker.invoke(MuleInvoker.java:106)
at org.mule.module.cxf.MuleJAXWSInvoker.invoke(MuleJAXWSInvoker.java:47)
at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:75)
.....
.....
Caused by: java.lang.NullPointerException
at org.mule.module.cxf.MuleInvoker.invoke(MuleInvoker.java:60)
... 29 more
Please help me understand what I missing here.
Note: I have tried the Mule way of implementing the security on jaxws using cxf:ws-security and my service is working and giving proper response.

Your cxf jaxws-service should be as below. Then it should work.
<http:inbound-endpoint address="http://localhost:8080/HelloService" exchange-pattern="request-response">
<cxf:jaxws-service serviceClass="com.example.service.HelloServiceImpl" >
<cxf:properties>
<spring:entry key="ws-security.ut.validator" value-ref="customUsernameTokenValidator" ></spring:entry>
<spring:entry key="ws-security.callback-handler" value-ref="myPasswordCallback" ></spring:entry>
</cxf:properties>
</cxf:jaxws-service>

Related

camel cxf - how to send soap request response in email

Here is my spring configuration.
Spring.xml
-------------
<!-- Outgoing SOAP client endpoint -->
<cxf:cxfEndpoint id="serviceEndpoint" address="${endpointAddress}"
wsdlURL="${wsdlAddress}" endpointName="${portName}" serviceName="${serviceName}">
<!-- The interceptors - needed to log the SOAP requests and responses -->
<!-- They can be removed, when no logging is needed -->
<cxf:inInterceptors>
<ref bean="loggingInInterceptor" />
</cxf:inInterceptors>
<cxf:outInterceptors>
<ref bean="loggingOutInterceptor" />
</cxf:outInterceptors>
<cxf:outFaultInterceptors>
<ref bean="loggingOutInterceptor" />
</cxf:outFaultInterceptors>
<cxf:inFaultInterceptors>
<ref bean="loggingInInterceptor" />
</cxf:inFaultInterceptors>
<cxf:properties>
<entry key="dataFormat" value="PAYLOAD" />
</cxf:properties>
</cxf:cxfEndpoint>
<http:conduit name="*.http-conduit">
<http:tlsClientParameters disableCNCheck="${disableHostnameCheck}">
<sec:keyManagers keyPassword="${keystorePassword}">
<sec:keyStore type="JKS" password="${keystorePassword}"
file="${keystoreLocation}" />
</sec:keyManagers>
<sec:trustManagers>
<sec:keyStore type="JKS" password="${truststorePassword}"
file="${truststoreLocation}" />
</sec:trustManagers>
<sec:cipherSuitesFilter>
<!-- these filters ensure that a ciphersuite with export-suitable or
null encryption is used, but exclude anonymous Diffie-Hellman key change
as this is vulnerable to man-in-the-middle attacks -->
<sec:include>.*_EXPORT_.*</sec:include>
<sec:include>.*_EXPORT1024_.*</sec:include>
<sec:include>.*_WITH_DES_.*</sec:include>
<sec:include>.*_WITH_AES_.*</sec:include>
<sec:include>.*_WITH_NULL_.*</sec:include>
<sec:exclude>.*_DH_anon_.*</sec:exclude>
</sec:cipherSuitesFilter>
</http:tlsClientParameters>
<http:client AutoRedirect="true" Connection="Keep-Alive"
ReceiveTimeout="${connectionTimeout}" ConnectionTimeout="${connectionTimeout}" />
</http:conduit>
Here is the Camel route configuration
-------------
<from ...
<to uri="cxf:bean:serviceEndpoint" />
This works well and we can have the soap request/response logged into the log file. Here soap request with soap header is generated by cxf.
Do we have a way to capture the soap request and response into camel Exchange? I have to send an email attached with soap request and response if the service call is failed.
Have tried using thread local but it doesn't seems to work expected.
Suggestion:
You have it in CXF Interceptors - take a look at them.
I guess, you can send your e-mail out of it.
Start from org.apache.cxf.phase.AbstractPhaseInterceptor class - there are bunch of different ones for different phases.
P.S. From first glance org.apache.cxf.binding.soap.saaj.SAAJInInterceptor and
org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor could be good candidates...

Mule Standalone 3.8.1 ClassDefNotFoundError when sending a stream of HTTP requests with big payload at high concurrency

I'm pretty new to MuleESB. I'm using Mule Standalone 3.8.1 with a configuration to filter HTTP requests using the xpath3() function. The configuration I have used is as follows.
<http:listener-config name="HTTP_Listener_Configuration" host="localhost" port="8081" />
<http:request-config name="HTTP_Request_Configuration" host="example.com" port="8081" basePath="basePath" responseTimeout="120000" />
<custom-transformer name="XML_Transformer" class="org.mule.module.xml.transformer.XmlToOutputHandler"/>
<message-properties-transformer name="Response_Error_Transformer">
<add-message-property key="http.status" value="500"/>
<add-message-property key="Content-Type" value="text/xml" />
</message-properties-transformer>
<message-properties-transformer name="Response_Transformer">
<add-message-property key="Content-Type" value="text/xml" />
</message-properties-transformer>
<set-payload name="Create_Error_Response" value="
<PurchaseOrder PurchaseOrderNumber="99503" OrderDate="1999-10-20">
<fault>
<code>500</code>
<message>#[flowVars['errorMessage']]</message>
</fault>
</PurchaseOrder>" />
<flow name="Choice_Flow">
<http:listener config-ref="HTTP_Listener_Configuration" path="productFilter" />
<choice>
<when expression="#[xpath3('//Item[1]/ProductName') == 'Laptop']">
<transformer ref="XML_Transformer"/>
<http:request config-ref="HTTP_Request_Configuration" path="EchoService" method="POST" />
<flow-ref name="Response_Transformer" />
</when>
<otherwise>
<flow-ref name="Response_Error_Transformer" />
<set-variable variableName="errorMessage" value="First item must be a Laptop" />
<flow-ref name="Create_Error_Response" />
</otherwise>
</choice>
</flow>
When I'm sending HTTP requests at 10 threads it's working fine. But, then when I tried sending requests at 500 threads, some of the requests got failed. The request is an XML with 2500 Item elements. I don't see any descriptive errors in the logs or anywhere, but the requests got failed. After this happens, some of the requests got failed even for small thread numbers, and I couldn't find any error in files in the logs directory. Only error I see in the mule.log file is as follows. This is written at the first occurrence of this error. Then, simply, nothing.
Exception: java.lang.NoClassDefFoundError thrown from the UncaughtExceptionHandler in thread "[default].http.listener(6)"
Can someone please explain me what's going on here? How to do this without any error? Is something wrong with my configuration?

Is it possible to add a security url in a Mule Flow, like Spring Security?

For example, in Spring I use the following code:
<http pattern="/users(?!\/emails).*" request-matcher="regex" create-session="stateless" entry-point-ref="authenticationEntryPoint" use-expressions="true"
xmlns="http://www.springframework.org/schema/security">
<anonymous enabled="false" />
<intercept-url method="GET" pattern="/user(?:([^/](?s).*)?)" />
So, on Mule I want to add security at the beginning of the Flow or (if possible), to configure the <intercept-url> tags.
And if possible, can I do this on Community Edition?
To answer your question in points:-
Yes, it is possible in Mule Community Edition to add security using Spring security as it has support for Basic Authentication
For your above requirement you need to implement Spring security in Mule
Mule can be configured with Spring security to provide Basic Authentication with username and password.
Whenever you hit the service, it will ask for username and password for that service.
So, this answer your question of implementing security at the beginning of the flow.
A simple example would be :-
<spring:beans>
<ss:authentication-manager alias="authenticationManager">
<ss:authentication-provider>
<ss:user-service id="userService">
<ss:user name="john" password="abc123" authorities="ROLE_ADMIN" />
<ss:user name="anon" password="anon" authorities="ROLE_ANON" />
</ss:user-service>
</ss:authentication-provider>
</ss:authentication-manager>
</spring:beans>
<mule-ss:security-manager>
<mule-ss:delegate-security-provider name="memory-provider" delegate-ref="authenticationManager" />
</mule-ss:security-manager>
<http:listener-config name="HTTP_Listener_Configuration" host="localhost" port="8081" doc:name="HTTP Listener Configuration" />
<flow name="SpringExampleFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="HTTP"/>
<http:basic-security-filter realm="mule-realm"/>
<logger level="INFO" message="passed security successfully !!! " doc:name="Logger"/>
</flow>
</mule>
The spring security can also be configured to provide role based support where multiple users involve with <mule-ss:authorization-filter/>.
So, you can filter the users based on their roles.
Some example you can refer here to get more ideas on it and it's implementation :- http://confluex.com/blog/http-inbound-endpoint-basic-authentication/
and
https://developer.mulesoft.com/docs/display/current/Configuring+the+Spring+Security+Manager

HTTP SOAP Post Request

I need to send HTTP Request to publish some data in a WS
E.g:
http://localhost:8081/hello/publishAMANSequence/filter/sequenceGenerationTime=1696-09-01T00:00:00Z&AMANId=B1&landingSequenceEntry=11234567890EST
I take this fault from server:
Parameter should be ordered in the following sequence: [sequenceGenerationTime, AMANId, landingSequenceEntry]
I'm doing something wrong in the order?
mule flow:
<jms:activemq-connector name="Active_MQ1" brokerURL="tcp://localhost:61616" validateConnections="true" doc:name="Active MQ"/>
<flow name="jmsFlow1" doc:name="jmsFlow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" path="hello" doc:name="HTTP"/>
<cxf:jaxws-service doc:name="SOAP" serviceClass="aero.itec.amansequenceservice.AMANSequenceInfo"/>
<component doc:name="Java" class="implementations.AMANSequenceImpl"/>
<mulexml:object-to-xml-transformer doc:name="Object to XML"/>
<jms:outbound-endpoint queue="StudioIN" connector-ref="Active_MQ1" doc:name="JMS"/>
<logger message="#[message.payload]" level="INFO" doc:name="Logger"/>
</flow>
The url which you have provided is wrong. There should be a questionmark(?) after "filter". Then only it will consider it as parameters
http://localhost:8081/hello/publishAMANSequence/filter?sequenceGenerationTime=1696-09-01T00:00:00Z&AMANId=B1&landingSequenceEntry=11234567890EST
Moreover if you are trying to access a webservice you can't do that with a HTTP GET. You need to send it as a SOAP request. You can use APIs like CXF, AXIS etc.
Following this tutorial ~
I create a flow for publish the WS , that have an inbound-endpoint where I do the request
publish.flow:
<jms:activemq-connector name="Active_MQ1" brokerURL="tcp://localhost:61616" validateConnections="true" doc:name="Active MQ"/>
<flow name="jmsFlow1" doc:name="jmsFlow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" path="hello" doc:name="HTTP"/>
<cxf:jaxws-service doc:name="SOAP" serviceClass="aero.itec.amansequenceservice.AMANSequenceInfo" >
<cxf:jaxb-databinding/>
<cxf:inInterceptors>
<spring:bean class="org.apache.cxf.interceptor.LoggingInInterceptor" />
</cxf:inInterceptors>
<cxf:outInterceptors>
<spring:bean class="org.apache.cxf.interceptor.LoggingOutInterceptor" />
</cxf:outInterceptors>
</cxf:jaxws-service>
<component doc:name="Java" class="implementations.AMANSequenceImpl"/>
<object-to-string-transformer doc:name="Object to String"/>
<jms:outbound-endpoint queue="StudioIN" connector-ref="Active_MQ1" doc:name="JMS"/>
<logger message="#[message.payload]" level="INFO" doc:name="Logger"/>
</flow>
Then I create a client.class where I set the variable values:
client.java
public class AMANwsClient extends AbstractTransformer{
#Override
protected Object doTransform(Object src, String enc)
throws TransformerException {
AMANSequence sequence = new AMANSequence();
XMLGregorianCalendar fec;
sequence.setSequenceGenerationTime(fec);
sequence.setAMANId("AA");
System.out.println(sequence);
return sequence;
}
This class is used like a transformer, we don't need to pass parameters in the url, only need to connect to the endpoint URL
Finally, create a client.flow
<custom-transformer class="implementations.AMANwsClient" name="AMANwsClient" />
<flow name="csvPublisher">
<transformer ref="AMANwsClient" />
<object-to-string-transformer doc:name="Object to String"/>
<outbound-endpoint address="http://localhost:63081/hello" exchange-pattern="request-response">
<cxf:jaxws-client clientClass="aero.itec.amansequenceservice.AMANSequenceInfo_Service" port="AMANSequenceInfoService" operation="publishAMANSequence">
<cxf:inInterceptors>
<spring:bean class="org.apache.cxf.interceptor.LoggingInInterceptor" />
</cxf:inInterceptors>
<cxf:outInterceptors>
<spring:bean class="org.apache.cxf.interceptor.LoggingOutInterceptor" />
</cxf:outInterceptors>
</cxf:jaxws-client>
</outbound-endpoint>
</flow>
Now I can save the payload into a JMS Queue and reproduce the payload from Browser, console and JMS.
If you have some suggestion to improve program performance, I'm open to listen to it.
Put http://localhost:8081/hello?wsdl in SOAPUI ... It will create the request and response there ... then you can pass the values in the request and invoke the webservice ...
Please check the following for your reference :-
http://developers-blog.org/blog/default/Webservice-testing-with-soapUI and http://quicksoftwaretesting.com/soapui-web-service-testing-tool/

camel cxf client soap fault handling

I'm using camel and cxf component to get some data from web-service. In some case web-service returns standard soap:fault.
I have the next steps:
<camel:route id="someId">
<camel:onException useOriginalMessage="false">
<camel:exception>java.lang.Exception</camel:exception>
<camel:handled>
<camel:constant>false</camel:constant>
</camel:handled>
<camel:process ref="defaultNaoIntegrationErrorHandler" />
<camel:to uri="ref:naointegration.checkAvailability.jms.error.queue" />
</camel:onException>
<camel:from uri="direct:naoCheckAvailabilityOut" />
<camel:marshal ref="soapjaxbSAP" />
<camel:to id="naoCheckAvailabilityEndpoint" uri="cxf:bean:naoCheckAvailabilityEndpoint" />
<camel:unmarshal ref="soapjaxbSAP" />
</camel:route>
where naoCheckAvailabilityEndpoint is:
<cxf:cxfEndpoint id="naoCheckAvailabilityEndpoint"
address="${naointegration.I011.CheckAvailability.soap.address}"
endpointName="s:checkAvailabilityEndpoint" serviceName="s:SOAPService"
xmlns:s="http://www.example.com/test">
<cxf:properties>
<entry key="dataFormat" value="MESSAGE" />
<entry key="setDefaultBus" value="true" />
</cxf:properties>
<cxf:outInterceptors>
<ref bean="logOutbound" />
</cxf:outInterceptors>
<cxf:inFaultInterceptors>
<ref bean="logOutbound" />
</cxf:inFaultInterceptors>
</cxf:cxfEndpoint>
If I'm getting normal soap message everything is ok. And when I'm getting soap foalt/http 500 I have just string message which contains soap message (xml) with soap fault.
Reading cxf and camel mail lists on like problems I understood cxf endpoint should throw exception if there soap foalt, exception of type org.apache.cxf.binding.soap.SoapFault, but I can not get it.
The goal is onException clause do handling of soap fault exception.
Any suggestions?
You are using the MESSAGE data format, which means the camel-cxf endpoint just pass the stream from the transport, it will not read the under layer message, so the camel-cxf endpoint cannot tell which message is normal soap message or soap fault message.
If you want to let the camel route deal with the soap fault, you need to use the PAYLOAD or POJO data format.

Categories