Apache CXF 2 Web Services - Custom Service Location - cxf

I have a web service which works fine. I'm trying to build a client to consume this service.
One constraint that I have is that my call has to go via a proxy server for logging (third party hosting provider). My problem is that I can specify the proxy as the WSDL location and that works fine. The resulting WSDL that is returned specifies the original service address:
I have configures my WSDL location at the proxy:
http://[proxy ip address]/csp/sql/ws.Booking.BookingService2.cls?wsdl=1
The WSDL shows:
<service name="Booking">
<port name="BookingSoap" binding="s0:BookingSoap">
<soap:address location="https://alpha2.premier.com:443/
csp/sql/ws.Booking.BookingService2.cls"/>
</port>
</service>
I want to call this service using the proxy address (192.168.98.45).
Does anyone have an idea how to call a custom service location? In the generated CXF code I can specify a WSDL location and a service name but not service location.
Thanks in advance.
Al

I have managed to find a/the solution for this.
I changed the ENDPOINT_ADDRESS_PROPERTY on the binding provider or the port. Here is my code to instantiate the web service that was generated by CXF:
com.micro.bartws.booking.Booking ss = new com.micro.bartws.booking.Booking(wsdl);
BookingSoap port = ss.getBookingSoap();
/* Set NEW Endpoint Location */
String endpointURL = hubProperties.getProperty("intouchservicelocation");
BindingProvider bp = (BindingProvider)port;
bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpointURL);
So the WSDL is imported and afgter we change the End point. IT works a treat.
Thanks

Related

Errors in add WCF service references?

My WCF project is OK, no errors, I try browse SVC file, it works well.
But when I add this WCF references, it throw errors :
There was an error downloading 'http://MyIPAddress/BKKService/BService.svc/_vti_bin/ListData.svc/$metadata'.
The request failed with HTTP status 404: Not Found.
Metadata contains a reference that cannot be resolved: 'http://MyIPAddress/BKKService/BService.svc'.
There was no endpoint listening at http://MyIPAddress/BKKService/BService.svc that could accept the message.
Please help me to solve this issue.
This is my web.config file
<services>
<service name="BKKService.BService">
<endpoint address="BKKService" binding="basicHttpBinding"
bindingConfiguration="basicHttp" contract="BKKService.IBService"/>
<host>
<baseAddresses>
<add baseAddress="http://MyIPAddress/BKKService/BService.svc"/>
</baseAddresses>
</host>
</service>
</services>
You can specify an absolute address for each endpoint associated with the service or you can provide a base address for the ServiceHost of a service and then specify an address for each endpoint associated with this service that is defined relative to this base address.
When hosting with IIS, you do not manage the ServiceHost instance yourself. The base address is always the address specified in the .svc file for the service when hosting in IIS. So you must use relative endpoint addresses for IIS-hosted service endpoints.
So "http://MyIPAddress/BKKService/BService.svc" would not work, you need to use the .svc file address. If you use IIS express, the address for adding service reference should be the url when you browse the svc file. If you use IIS, it is the address specified for .svc file in IIS.

CXF WS-Trust service certificate configuration

Objective: Get information (using Apache CXF) from a third party (thus no control or access to the service backend) web service
which use WS-Trust i.e. it authenticates the user using a Secure Token Service in this case with UsernameToken authentication.
I have spent a LONG time trying to learn about the WS-* security standards and at the same time trying out different frameworks and
tools (Axis, Apache CXF, METRO with NetBeans, Microsoft .net, SoapUI plugin for Eclipse etc.) to connect to a specific service in
the cloud. I am trying to develop a backend client that fetch information from the service. Apache CXF is attractive here
because it seems to be the only Java framework which does not assume that everyone connecting to web services use clients deployed on a web application server.
The service providers have provided the necessary certificates and user credentials to connect to the service using STS.
They have also provided a detailed user guide using NetBeans and METRO to create a web application that is deployed on a GlassFish server.
I have followed this guide and managed to get data from the web service. Conclusion so far: The certificates are valid.
There are three certificates stored in a keystore (including chains):
webservice-encryption-certificate.cer (keystore alias: webservice-encryption)
token-signing-certificate.cer (keystore alias:
token-signing)
token-encryption-certificate.cer (keystore alias: token-encryption)
=================================================================
NetBeans configuration:
Service client:
Keystore -> token-signing-certificate.cer
Truststore -> webservice-encryption-certificate.cer
STS client:
Truststore -> token-encryption-certificate.cer
Username -> user
Password -> xxx
=================================================================
THE BIG QUESTION: How can I make a similar configuration in CXF as in NetBeans?
I'm using CXF version: 3.0.2
"Translating" this to CXF gives me the follownig exception:
WARNING: Interceptor for {http://schemas.microsoft.com/ws/2008/06/identity/securitytokenservice}SecurityTokenService#{http://schemas.microsoft.com/ws/2008/06/identity/securitytokenservice}Trust13IssueAsync has thrown exception, unwinding now
org.apache.cxf.binding.soap.SoapFault: The signature or decryption was invalid
at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.createSoapFault(WSS4JInInterceptor.java:841)
Here is what i tried in CXF (amongst MANY other things):
MyService service = new MyService(); // Stub created from WSDL (real service name has been renamed to MyService)
MyServiceInterface port = service.getPort();
org.apache.cxf.endpoint.Client client = ClientProxy.getClient(port);
Bus bus = ((EndpointImpl) client.getEndpoint()).getBus();
STSClient stsClient = new STSClient(bus);
stsClient.setWsdlLocation("https://login.some-domain.com/adfs/services/trust/mex"); // Web service is using ADFS 2.0 with MEX
stsClient.setServiceQName(new QName("http://schemas.microsoft.com/ws/2008/06/identity/securitytokenservice", "SecurityTokenService"));
stsClient.setEndpointQName(new QName("http://schemas.microsoft.com/ws/2008/06/identity/securitytokenservice", "UserNameWSTrustBinding_IWSTrust13Async"));
stsClient.setSendRenewing(false);
stsClient.getRequestContext().put("ws-security.sts.token.properties", "clientTruststore.properties");
stsClient.getRequestContext().put("ws-security.sts.token.username", "webservice-encryption"); // MOST LIKELY WRONG - WHERE DO I PUT THIS CERTIFICATE?
Map<String, Object> ctx = ((BindingProvider) port).getRequestContext();
ctx.put("ws-security.sts.prefer-wsmex", true); // If set to false some policies will not be satisfied
ctx.put("ws-security.username", "user"); // REQUIRED OR FAIL WITH: No username available
ctx.put("ws-security.password", "xxx"); // REQUIRED OR FAIL: No username available
ctx.put("ws-security.encryption.properties", "clientTruststore.properties"); // REQUIRED OR FAIL WITH: A encryption username needs to be declared
ctx.put("ws-security.encryption.username", "token-encryption"); // REQUIRED OR FAIL WITH: A encryption username needs to be declared
ctx.put("ws-security.signature.properties", "clientTruststore.properties");
ctx.put("ws-security.signature.username", "token-signing");
ctx.put("ws-security.is-bsp-compliant", "false");
ctx.put("ws-security.sts.client", stsClient);
port.callSomething(createMyRequestObject());
I have tried to "decrypt" the meaning of the properties used in the code snippet above based on the following link (along many other tutorials and articles on the subject) to make sense in relation to WS-Trust and the certificates at hand.
http://cxf.apache.org/javadoc/latest/org/apache/cxf/ws/security/SecurityConstants.html
I have tried all sorts of combinations using the constants but with no success.
How do I "pass" the service certificate (webservice-encryption) to the STS to tell it "this is the service that I want to use"?
By the way I have captured the traffic with Fiddler, and the request looks perfectly right compared to traffic captured with the NetBeans solution i.e. it contains timestamp, encrypted sections etc.
I KEEP GETTING "The signature or decryption was invalid"
Can anyone help please?
What does the response method from the STS look like? Is it an error message or does it look like the call succeeded? If it is an error message then it looks like you may be using the wrong certificates...you will need to enable logging on the service to figure out what the exact error is. If the call succeeded, then enable DEBUG logging on the client side and see what the problem is.
Colm.
We had a similar problem. Perhaps you must add JCE Unlimited Strength Policy jar files to JDK?

Create proxy for Apache CXF Web services in wso2 ESB

I am a very beginner in ESB. So, kindly excuse me for this basic question.
Currently we have web services created with Apache CXF and Spring running. Now, we need to create proxy services for these in WSo2 ESB. Can someone please let us know how can we do this?
I created Pass Through proxy and use wsdl definition as from URL, but when i use try it option i get he endpoint reference (EPR) for the Operation not found is /services/ and the WSA Action = null.
If this EPR was previously reachable,please contact the server administrator.
Since ESB 4.6, pass-through transport is enabled by default : The message body is not build so, SOAP Body based dispatching is not supported => in this case, the error you're speaking about is thrown
One solution could be to add this parameter in your proxy conf : <parameter name="disableOperationValidation" locked="false">true</parameter>
Have a look there for other options : Using WSO2 ESB PassThrough Proxy on WebLogic (Spring) Web Service
How did you create the proxy service? If you have the wsdl of the Backend service you can use it to create the proxy service like follows.
<proxy xmlns="http://ws.apache.org/ns/synapse" name="testProxy2" transports="https,http" statistics="disable" trace="disable" startOnLoad="true">
<target>
<outSequence>
<send/>
</outSequence>
<endpoint>
<wsdl service="SimpleStockQuoteService"
port="SimpleStockQuoteServiceHttpSoap11Endpoint"
uri="http://localhost:9000/services/SimpleStockQuoteService?wsdl"/>
</endpoint>
</target>
<description/>
</proxy>
The ESB gets the endpoint url from the Service name and Port defined in the WSDL. For SOAP 1.1 the WSA action will be the SOAPAction header and for SOAP 1.2 the WSA action goes with the action element of Content-Type header. For example,
Content-Type: application/soap+xml;charset=UTF-8;action="TheSoapAction"
Try to use a SOAP client like SOAPUI to test your proxy service.

Opensso with SSL Configuration issue in F5 Load Balancers

We are having a web application architecture where our application EAR is deployed in appServer configured with non-ssl Http Port Listener. Every request is routing via F5 Load Balancer-> Web Server-> App Server.
In Load Balancer, we have set an iRule where every Http Request is forwarded to Https set on port 443 and our application is working fine. Now we are trying to implement a SSO using OpenSSO federation solution and SAML Technology. we have deployed the opensso with the non-ssl http listener configuration in our app server.
now when we try to access the opensso using the url xhttp://domain_name/opensso(dummy protocol), it is redirected as per iRule set on the Load Balancer as xhttps://domain_name/opensso. But in the appearing configuration page of opensso, the server URL is populated as xhttp://domain_name only instead of xhttps://domain_name. Likewise, the same approach is followed to populate all the URL properties throughout the opensso configuration. So when I tried to generate the metadata using ssoadm GUI, In the form action attribute the url is formed as 'http' and the request method is passed as 'POST' only as per Opensso convention. But when it is redirected to 'https' as per the Load Balancer Rule the Request method is passed as 'GET' instead of post and the opensso validation fails and throwing the error as 'HTTP Post Protocol is required.
So the issue here is, By default the opensso URL properties should be populated with "https" instead of "http". I would like to know what is the wrong configuration done here. how we could resolve this issue? Thanks.
I think that you will find that the answer actually lies within your application server, not the application itself. You need to indicate to the servlet that it is being proxied, and that it is responsible for creating URLs with the HTTPS scheme, not HTTP.
If you're using Tomcat or a derivative, you can modify the server.xml to include the following:
proxyPort="443"
proxyName="www.domain_name.com"
scheme="https"
secure="true"
You can configure the load balancer to redirect to https with a 307 http status code which informs the client to use the original request method. If POST was the original request method then following the redirect the client will continue to use POST instead of a GET.
HTTP::respond 307 Location "https://[HTTP::host][HTTP::uri]"

How to get client certificate inside web method at asp.net web forms c#?

I configure IIS to get certificates from client. And I can easily get client certificate inside event handler, for example Page_Load
HttpClientCertificate cert = Request.ClientCertificate;
Now I need to create web method what will get client name from certificate and return data for this client. But how can I get client certificate inside static web method where I don't have access to Request?
In any method, including in a static method, you can use HttpContext.Current. If this is non-null, then you can access the Request property. If that is non-null, then you can access the ClientCertificate property.
Of course, it may be null...

Resources