call a method on Navision webservice using NTML authentication using Java - java

I've created a SOAP web-service client on Netbeans. The web-service is exposed on Navision with NTML authentication. During class generation, a login pop-up picks the required credentials and uses them for authentication.
The issue is once the classes are generated and I try to invoke any method;
ServicePort webservice_port = new WService().getServicePort();
webservice_port.retrieveData();
I get an exception.
java.io.IOException: Server returned HTTP response code: 401 for URL: ...
Exception in thread "main" com.sun.xml.ws.wsdl.parser.InaccessibleWSDLException: 2 counts of InaccessibleWSDLException.
at com.sun.xml.ws.wsdl.parser.RuntimeWSDLParser.tryWithMex(RuntimeWSDLParser.java:275)
at com.sun.xml.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:246)
at com.sun.xml.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:209)
at com.sun.xml.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:178)
at com.sun.xml.ws.client.WSServiceDelegate.parseWSDL(WSServiceDelegate.java:363)
at com.sun.xml.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:321)
at com.sun.xml.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:230)
at com.sun.xml.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:211)
at com.sun.xml.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:207)
at com.sun.xml.ws.spi.ProviderImpl.createServiceDelegate(ProviderImpl.java:114)
at javax.xml.ws.Service.<init>(Service.java:57)
at com.ntml.remote.MSACCO.<init>(MSACCO.java:42)
Is this an issue with NTLM authentication or is there another way to pass the credentials?

Found a working solution. Injecting an authentication mechanism to the client using the web service port.
Port webservice_port = new Wservice().getServicePort();
Client client = ClientProxy.getClient(webservice_port);
HTTPConduit conduit = (HTTPConduit) client.getConduit();
AuthorizationPolicy authorization = conduit.getAuthorization();
authorization.setUserName(username);
authorization.setPassword(password);
conduit.getClient().setAllowChunking(false);
conduit.getClient().setAutoRedirect(true);
webservice_port.callWebMethod();

Related

Security Token issue with WCF Service with wsHttpBinding Axis2 in Java Client

I have to use a WCF service in a Java client. I have generated proxy code using Axis2 library. I have successfully configured proxy classes but getting issue when calling WCF service method.
Following is the code in my java client.
ServiceXMLStub stub = new ServiceXMLStub("https://qa1-myservice.com/integration/ServiceXML.svc");
GetMetadata meta = new GetMetadata();
meta.setStateCode("WA");
meta.setUserName("tpstester1");
stub._getServiceClient().getOptions().setProperty(Constants.Configuration.MESSAGE_TYPE,HTTPConstants.MEDIA_TYPE_APPLICATION_ECHO_XML);
stub._getServiceClient().getOptions().setProperty(Constants.Configuration.DISABLE_SOAP_ACTION,Boolean.TRUE);
stub._getServiceClient().engageModule("addressing");
stub._getServiceClient().getOptions().setUserName("myuser");
stub._getServiceClient().getOptions().setPassword("myp#ssw0rd");
GetMetadataResponse response = stub.getMetadata(meta);
Following is the issue I am getting when calling this service from this client.
org.apache.axis2.AxisFault: The message could not be processed. This is most likely because the
action 'http://Integration.ContractsXML/IServiceXML/GetMetadata' is incorrect or because the message
contains an invalid or expired security context token or because there is a mismatch between
bindings.
The security context token would be invalid if the service aborted the channel due to inactivity. To
prevent the service from aborting idle sessions prematurely increase the Receive timeout on the
service endpoint's binding.
I tested this code in .Net client and it works fine there
ServiceReference1.ServiceXMLClient serviceClient = new ServiceReference1.ServiceXMLClient();
serviceClient.ClientCredentials.UserName.UserName = "myuser";
serviceClient.ClientCredentials.UserName.Password = "myp#ssw0rd";
var result = serviceClient.GetMetadata("tpstester1", "SA");
What am I missing here ?

CXF + wsdl2java + authentication

I created the jar from the WSDL for my client using the wsdl2java command. Now, I need to know how I can authenticate my client in order to complete an operation?
I am using CXF 2.7.16. I created my service using the generated class MyApp_Service, I am struggling with this. Isn't there a simple way to tell my client the credentials it should use to gain access to the web service?
I read about the Spring configuration, however I am unable to figure out if it applies to my case and how if yes. I tried to cast the MyApp_Service class to BindingProvider in order to use the method which consist to put the USERNAME and PASSWORD properties in the context with a value. However, MyApp_Service cannot be cast to BindingProvider.
This is my first web service client application ever. So, any help will be welcomed.
Update 2015-05-28: I tried to define the AuthenticationPolicy but is seems not working. Here is the code:
Client client = JaxWsDynamicClientFactory.newInstance().createClient(wsdlUrl);
ClientImpl clt = (ClientImpl) client;
HTTPConduit cc = (HTTPConduit) clt.getConduit();
org.apache.cxf.configuration.security.ObjectFactory secOF = new org.apache.cxf.configuration.security.ObjectFactory();
AuthorizationPolicy ap = secOF.createAuthorizationPolicy();
ap.setUserName(usagerWS);
ap.setPassword(mdpWS);
ap.setAuthorizationType("Basic");
cc.setAuthorization(ap);
Sniffing with WireShark, the Authorization header is clearly missing in the HTTP request.
What is missing?
Problem solved, here is the solution:
MyApp_Service service = new MyApp_Service(wsdlUrl, new QName(namespace, serviceName));
MyApp port = service.getMyApp();
// Set credentials
Map<String, Object> reqCtxt = ((javax.xml.ws.BindingProvider) port).getRequestContext();
reqCtxt.put(javax.xml.ws.BindingProvider.USERNAME_PROPERTY, username);
reqCtxt.put(javax.xml.ws.BindingProvider.PASSWORD_PROPERTY, password);
No more usage of the dynamic client. Only the classes generated with wsdl2java are used.

Validating client credentials on a server using Java SimpleFramework

I am developing a SSL/TLS enabled server using the Java SimpleFramework. I am wondering how to validate client authentications on the server.
On the server side, I am extending org.simpleframework.http.core.ContainerServer and overriding the process() method as follows:
#Override
public void process(Socket socket) throws IOException {
// Ensures client authentication is required
socket.getEngine().setNeedClientAuth(true);
super.process(socket);
}
This is to make sure that clients authenticate. Note that if I remove the call to setNeedClientAuth(), my program works perfectly.
On the client side, the following code is used:
HttpClient client = new HttpClient();
Credentials defaultcreds = new UsernamePasswordCredentials("username", "password");
client.getState().setCredentials(AuthScope.ANY, defaultcreds);
GetMethod get = new GetMethod("https://url.to.server");
get.setDoAuthentication(true);
client.executeMethod(get);
When enabling authentication requirement, I get the following exception:
javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
I am guessing this relates to the fact that the passed credentials is never validated.
To summarize my question, how should I proceed to validate clients on the server?

Java SOAP web service over SSL with basic authentication, connection refused

I am trying to send a SOAP request over SSL with my own little Java client and it fails with "java.net.ConnectException: Connection refused". The same request sent with SOAPUI does not fail, I get a valid response from the server.
This is the code I am trying to run:
public static void main(String[] args) throws MalformedURLException {
System.setProperty("sun.security.ssl.allowUnsafeRenegotiation", "true");
SSLUtilities.trustAllHttpsCertificates();
URL wsdlURL = new URL(MY_WSDL_LOCATION);
QName serviceName = new QName(MY_QNAME, NAME_OF_SERVICE);
Service service = Service.create(wsdlURL, serviceName);
Order myOrder = service.getPort(Order.class);
BindingProvider portBP = (BindingProvider) myOrder;
String urlUsed = (String) portBP.getRequestContext().
get(BindingProvider.ENDPOINT_ADDRESS_PROPERTY);
System.out.println("Using URL: " + urlUsed);
((BindingProvider)myOrder).getRequestContext().put(
BindingProvider.USERNAME_PROPERTY, CORRECT_USERNAME);
((BindingProvider)myOrder).getRequestContext().put(
BindingProvider.PASSWORD_PROPERTY, CORRECT_PASSWORD);
AliveRequest aliveRequest = new AliveRequest();
MerchantInfo merchInfo = new MerchantInfo();
merchInfo.setMerchantId(CORRECT_MERCHANT_ID);
aliveRequest.setMerchantInfo(merchInfo);
AliveResponse aliveResponse = myOrder.alive(aliveRequest);
}
It fails with "java.net.ConnectException: Connection refused" exception. When I build a request from the same WSDL using SOAPUI, populate the same fields with same values and enter the same basic authentication credentials, a valid response is returned.
The problem was the fact that my Java client didn't send the request through the proxy, so my own company's firewall was blocking it. Unlike my own Java client, SOAPUI actually detects the proxy settings of the system (probably reads system environment variables) when SOAPUI's proxy settings are set "auto" (default). The solution was to set the following system properties:
-Dhttps.proxySet=true
-Dhttps.proxyHost=MY_PROXY_HOST
-Dhttps.proxyPort=MY_PROXY_PORT

Problem with passing SOAP headers using Apache CXF client

I am trying to implement a simple client for a webservice, the only problem I am facing with the webservice is, it has a generic endpoint: http://myserver3333.com:8080/ws/services and the way you lookup for web services deployed is via SOAP header.
So, for example, if you try to hit the service vis SOAP UI,
the endpoint I specify is: http://myserver3333.com:8080/ws/services
In the SOAP headers I specific the following:
SERVICE-NAME = MyAwesomeService
OPERATION-NAME = makeMeMoreAwesome
So, how can I do the same thing using apache cxf client?
My current code:
URL wsdlLocation = new URL("http://myserver3333.com:8080/ws/service");
MyAwesomeService service = new MyAwesomeService(wsdlLocation);
MyAwesomeServicePort port = service.getMyAwesomeServiceSOAPPort();
List<Header> headers = new ArrayList<Header>();
Header operationNameHeader = new Header(new QName("OPERATION-NAME"), "makeMeMoreAwesome",
new JAXBDataBinding(String.class));
Header serviceNameHeader = new Header(new QName("SERVICE-NAME"), "MyAwesomeService",
new JAXBDataBinding(String.class));
headers.add(operationNameHeader);
headers.add(serviceNameHeader);
BindingProvider bindingProvider = (BindingProvider)port;
bindingProvider.getRequestContext().put(Header.HEADER_LIST, headers);
MakeMeMoreAwesomeRequest request = new MakeMeMoreAwesomeRequest();
MakeMeMoreAwesomeResponse response = port.makeMeMoreAwesome(request);
System.out.println(response.getAck());
But when I run this, I get this error:
Exception in thread "main" com.sun.xml.ws.wsdl.parser.InaccessibleWSDLException: 2 counts of InaccessibleWSDLException.
java.io.IOException: Server returned HTTP response code: 500 for URL: http://myserver3333.com:8080/ws/services
java.io.IOException: Server returned HTTP response code: 500 for URL: http://myserver3333.com:8080/ws/services?wsdl
Which is correct because there is no WSDL at that location, it need to follow the soap header to get the service.
Update:
After two points from #Daniel Kulp I am here:
I added a new line: bindingProvider.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "http://myserver3333.com:8080/ws/services");
And now I get this error:
org.apache.cxf.binding.soap.SoapFault: "http://www.myserver.com/ws/services", the namespace on the "errorMessage" element, is not a valid SOAP version.
at org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor.readVersion(ReadHeadersInterceptor.java:115)
at org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor.handleMessage(ReadHeadersInterceptor.java:141)
at org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor.handleMessage(ReadHeadersInterceptor.java:60)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
at org.apache.cxf.endpoint.ClientImpl.onMessage(ClientImpl.java:771)
My assumption is, this error is same as this one. But I am not using ?wsdl. So, any suggestions?
2 comments:
1) You aren't picking up CXF. Check your classpath to make sure CXF is there and not the Sun/Oracle implementation. com.sun.xml.ws.wsdl.parser.InaccessibleWSDLException shows you are picking up the Sun implementation.
2) The URL passed into MyAwesomeService(wsdlLocation) MUST be a URL to the WSDL, not the endpoint itself.

Categories

Resources