Adding digest authentication to SOAP request - java

I'm trying to add digest authentication (username and password) to my SOAP request which uses org.apache.cxf (3.3.2) for classes generation. I've tried to append the username and password using the BindingProvider with no success:
MyServiceGeneratedClass soapClient = new MyServiceGeneratedClass();
MyServicePort port = soapClient.getMyServicePort();
BindingProvider bindingProvider = (BindingProvider)port;
bindingProvider.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "mySecretUsername");
bindingProvider.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "mySecretPassword");
The generated SOAP request does not contain the user and password.
Any ideas?

Similiar post is about Digest Authentication With Apache CXF
Maybe that solution might work for you as well :
MyService myService = new MyService("wsdl-url");
MyServicePort myServicePort = myService.getMyServicePort();
Client client = ClientProxy.getClient(myServicePort);
HTTPConduit http = (HTTPConduit) client.getConduit();
AuthorizationPolicy authPolicy = new AuthorizationPolicy();
authPolicy.setAuthorizationType("Digest");
authPolicy.setUserName("user");
authPolicy.setPassword("myPassword");
http.setAuthorization(authPolicy);
myServicePort.doSomething();

Related

Sign SOAP message with WS-Security

I need to consume a SOAP API which requests all the messages to be signed policy "SigOnly".
I've generated the client code from the WSDL using wsimport and I was expecting it to generate the code for signing as well but it's not.
MyWebservice service = new MyWebservice();
MyWebservicePortType port = service.getMyWebserviceSOAPportHttp();
// Build request
ObjectFactory objectFactory = new ObjectFactory();
MyRequest request = objectFactory.createMyRequest();
// Call endpoint
port.myRemoteMethod(request);
Is there an extra switch for the wsimport tool to generate code for signing or am I missing some steps in the client's code?
WS-Security is an extension to soap, so I don't think wsimport could handle it in code generation.
Anyway you can write your handler to add ws-security headers in your soap requests.
You can add a handler to your port in this way :
BindingProvider bp = (BindingProvider) port;
List<Handler> handlerChain = new ArrayList<Handler>();
handlerChain.add( new MyHandler() );
Binding binding = bp.getBinding();
binding.setHandlerChain(handlerChain);
MyHandler class must implement SOAPHandler.
This is an example of an implementation of handleMessage method of MyHandler, adding a header
#Override
public boolean handleMessage(SOAPMessageContext smc) {
Boolean outboundProperty = (Boolean) smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (outboundProperty.booleanValue()) {
SOAPEnvelope envelope = smc.getMessage().getSOAPPart().getEnvelope();
SOAPHeader header = envelope.addHeader();
SOAPElement security = header.addChildElement("Security", "wsse",
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
SOAPElement usernameToken = security.addChildElement("UsernameToken", "wsse");
SOAPElement username = usernameToken.addChildElement("Username", "wsse");
username.addTextNode("MyUser");
}
}

SOAP Services are working in SOAP UI but not Working via Code in java

Soap services are working fine after passing the parameters username and password under authentication tab in Soap UI but not working from java code.
Please find the Code as below:
ServicesLocator sl = new ServicesLocator();
ServicesSoapProxy proxy = new ServicesSoapProxy();
ServicesSoap serviceSoap = sl.getServicesSoap();
//Service s = new Service();
//Port port = s.getPort(); // if tried using service object s but s.getPort not coming in my code
Port port = (Port) sl.getPort(proxy.getEndpoint(),ServicesSoap.class);
BindingProvider prov = (BindingProvider)port;
prov.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "username");
prov.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "password");
//then calling SOAP Service
serviceSoap.callExternalSOAPSERVICE();
Error as shown below:
faultCode: {http://xml.apache.org/axis/}HTTP
faultSubcode:
faultString: (401)Unauthorized
faultActor:
faultNode:
faultDetail:
{}:return code: 401
Please suggest on this.
Set HTTP Header,
Authorization Basic "base64encoded username/password".
Something like below.
String authString = "username" + ":" + "password";
String authStringEnc = new BASE64Encoder().encode(authString.getBytes());
//Get the HTTP Header and set it like below.
objectXXX.header("Authorization", "Basic " + authStringEnc);"
//Call your service, now

Consuming soap service with NTLM Authentication

I am trying to consume a SOAP service with NTLM authentication by creating a NTLM engine (following instructions on http://hc.apache.org/httpcomponents-client-4.3.x/ntlm.html ) implemented AuthSchemeFactory and finally registered the AuthSchemeFactory to my HTTP Client. When I hit the service using my HTTP Client I get a reponse that "Status code - 415 , Message - The server cannot service the request because the media type is unsupported."
Can anybody tell how can I fix this issue of unsupported media to consume a NTLM-protected SOAP web service on Java platform. Is using JCIFS a correct option to conmsume NTLM protected service or are there any better approach(s). Thanks in advance.
DefaultHttpClient httpclient = new DefaultHttpClient();
httpclient.getAuthSchemes().register(AuthSchemes.NTLM,
new JCIFSNTLMSchemeFactory());
CredentialsProvider credsProvider = new BasicCredentialsProvider();
NTCredentials ntcred = new NTCredentials("USERNAME", "PASSWORD",
"HOST", "DOMAIN");
credsProvider.setCredentials(new AuthScope("HOST", 443,
AuthScope.ANY_REALM, "NTLM"), ntcred);
httpclient.setCredentialsProvider(credsProvider);
httpclient.getParams().setParameter(
CoreProtocolPNames.HTTP_CONTENT_CHARSET, "UTF-8");
Writer writer = new StringWriter();
writer.write("MY SOAP REQUEST BODY");
HttpPost httppost = new HttpPost(
"https://<HOST_NAME>/XiPay30WS.asmx");
httppost.setEntity(new StringEntity(writer.toString()));
httppost.setHeader("Content-Type",
"application/x-www-form-urlencoded");
HttpResponse httpresponse = httpclient.execute(
new HttpHost("HOST", 443, "https"),
httppost, new BasicHttpContext());
String statusCode = httpresponse.getStatusCode();
If you use Spring WS support:
Check this Solution
http://dolszewski.com/spring/sharepoint-web-services-spring-and-ntlm-authentication/
#Bean("navisionMessageSender")
public HttpComponentsMessageSender httpComponentsMessageSender() {
HttpComponentsMessageSender httpComponentsMessageSender = new HttpComponentsMessageSender();
String user = env.getProperty("navision.endpoint.user");
String password = env.getProperty("navision.endpoint.password");
String domain = env.getProperty("navision.endpoint.domain");
NTCredentials credentials = new NTCredentials(user, String.valueOf(password), null, domain);
httpComponentsMessageSender.setCredentials(credentials);
return httpComponentsMessageSender;
}
Sample python implementation with NTLM Auth with FLASK.
If you want to use with java , run the standalone flask code below and call the url (e.g POST request /dora/httpWithNTLM ) from java code by http request
from flask import Flask, render_template, flash, request, url_for, redirect, session , Response
import requests,sys,json
from requests_ntlm import HttpNtlmAuth
app = Flask(__name__)
#app.route("/dora/httpWithNTLM",methods=['POST'])
def invokeHTTPReqWithNTLM():
url =""
reqData = json.loads(request.data)
reqxml=request.data
headers = {}
headers["SOAPAction"] = "";
headers["Content-Type"] = "text/xml"
headers["Accept"] = "text/xml"
print("req headers "+str(request.headers))
r = requests.Request("POST",url,auth=HttpNtlmAuth('domain\\username','password'), data=reqxml, headers=headers)
prepared = r.prepare()
s = requests.Session()
resp = s.send(prepared)
print (resp.status_code)
return Response(resp.text.replace("<","<").replace(">",">"),resp.status_code)
if __name__ == '__main__':
app.run(host="0.0.0.0",port=5001)

CXF SOAP Client with NTLM to SharePoint

I am writing a SOAP client using CXF Framework (version: 2.7.8) for SharePoint 2007. I have followed the online documentation for adding NTLM support here. I have the client working and tracing the HTTP session shows that NTLM credentials are being sent, however, I am still receiving a 401 Unauthorized response.
Code:
Lists listService = new Lists();
ListsSoap port = listService.getListsSoap();
BindingProvider bp = (BindingProvider) port;
bp.getRequestContext().put("use.async.http.conduit", Boolean.TRUE);
Credentials creds = new NTCredentials(USER, PASS, "", DOMAIN);
bp.getRequestContext().put(Credentials.class.getName(), creds);
Client client = ClientProxy.getClient(proxy);
HTTPConduit http = (HTTPConduit) client.getConduit();
HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
httpClientPolicy.setConnectionTimeout(36000);
httpClientPolicy.setAllowChunking(false);
httpClientPolicy.setAutoRedirect(true);
http.setClient(httpClientPolicy);
// Build request and execute
Interestingly, I wrote a similar client using HTTP PUT for WebDAV to upload documents using Apache HTTPClient library, and was able to successfully authenticate using NTLM. Also, I was able to use SOAPUI to invoke the same Lists web service I am trying to build the Java client for and it successfully authenticated using NTLM as well.
I'm assuming the implementation of NTLM is different between CXF and HTTPClient. Any thoughts on what is wrong with my CXF implementation? Or how I can get it to mirror the HTTPClient implementation?
Please try this way!
HTTPConduit http = (HTTPConduit)client.getConduit();
AsyncHTTPConduit conduit = (AsyncHTTPConduit)http;
DefaultHttpAsyncClient defaultHttpAsyncClient;
defaultHttpAsyncClient = conduit.getHttpAsyncClient();
defaultHttpAsyncClient.getCredentialsProvider().setCredentials( AuthScope.ANY,
new NTCredentials( USER,PWD, "", DOM ) );
conduit.getClient().setAllowChunking( false );
conduit.getClient().setAutoRedirect( true );
#lamarvannoy, I also got this error. But I found another way. You don't need to cast HTTPConduit to AsyncHTTPConduit. Let's try this stuff:
public class Test {
static final String kuser = "yourDomain\\username";
static final String kpass = "yourPassword";
static class MyAuthenticator extends Authenticator {
public PasswordAuthentication getPasswordAuthentication() {
System.err.println("Feeding username and password for " + getRequestingScheme());
return (new PasswordAuthentication(kuser, kpass.toCharArray()));
}
}
public static void main(String[] args) throws Exception {
Authenticator.setDefault(new MyAuthenticator());
Lists listService = new Lists();
ListsSoap port = listService.getListsSoap();
Client client = ClientProxy.getClient(port);
HTTPConduit http = (HTTPConduit) client.getConduit();
HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
httpClientPolicy.setConnectionTimeout(36000);
httpClientPolicy.setAllowChunking(false);
http.setClient(httpClientPolicy);
String listName = "S030_main";
String rowLimit = "150";
ArrayList<String> listColumnNames = new ArrayList<String>();
listColumnNames.add("Title");
Test.displaySharePointList(port, listName, listColumnNames, rowLimit);
}
}
You may find the implementation of displaySharePointList() method in this post: http://davidsit.wordpress.com/2010/02/10/reading-a-sharepoint-list-with-java-tutorial/
I hope this will safe your and others time.
This works for me:
Client client = ClientProxy.getClient(port);
AsyncHTTPConduit conduit = (AsyncHTTPConduit)client.getConduit();
AuthorizationPolicy authorization = conduit.getAuthorization();
authorization.setUserName("domain\\username");
authorization.setPassword("password");
Actually this works for both NTLM and Basic
This is what I had to do to get mine to work:
// Include a version of WSDL in class path, make URL point to that
URL url = MyClient.class.getResource("previouslydownloaded.wsdl");
MyCxFService ws = new MyCxFService(url);
MyCxfClient client = ws.getMyCxfServicePort();
BindingProvider prov = ((BindingProvider) client);
Binding binding = prov.getBinding();
// Set Username and Password
if ((this.user != null) && (!this.user.isEmpty())) {
prov.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, this.user);
prov.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, this.passwd);
}
// Get address from config file to get rid error caused by using wsdl file:
// Caused by: java.lang.NullPointerException
// at org.apache.cxf.transport.http.URLConnectionHTTPConduit.createConnection(URLConnectionHTTPConduit.java:104)
prov.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, this.portAddress);
Hope that might help someone.

How to use Proxy authentication with Jersey and Apache Http client?

I am using jersey client with ApacheConnection Provider.
Builder builder = RequestConfig.custom().setConnectTimeout(timeout);
List<Proxy> proxies = ProxyManager.getInstance().select(baseUrl.toURI());
if (useProxy) {
...
builder.setProxy(new HttpHost(proxyUri.getHost(), proxyUri.getPort()));
}
RequestConfig requestConfig = builder.build();
final ClientConfig clientConfig = new ClientConfig();
clientConfig.property(ApacheClientProperties.REQUEST_CONFIG, requestConfig);
clientConfig.connectorProvider(new ApacheConnectorProvider());
client = ClientBuilder.newBuilder().withConfig(clientConfig).sslContext(getSSLContext()).build();
client.property(ClientProperties.CONNECT_TIMEOUT, 5000);
But how to add username and password for Proxy authentication?
Seems like apache connection provider does not use the standard java proxy selector mechanisms.
I finally found the solution by myself. Unfortunately this is documented nowhere:
HttpHost proxyhost = new HttpHost(host,pw);
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(new AuthScope(proxyhost), new UsernamePasswordCredentials(user, pw));
clientConfig.property(ApacheClientProperties.CREDENTIALS_PROVIDER, credsProvider);
builder.setProxy(proxyhost);
I think you should add few more lines of code
builder.setProxy(proxyhost).setDefaultCredentialsProvider(credsProvider)
.setProxyAuthenticationStrategy(new ProxyAuthenticationStrategy());
otherwise it wont really authenticate the proxy host I feel. In your case it might be bypassing the proxy. ?

Categories