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)
Related
I am writing a program that needs to access the cPanel API (https://api.docs.cpanel.net). To use the API I need to be authenticated and have the cPanel session id so that I can build my URL. For example to add a new FTP user I would use the following URL - https://hostname.example.com:2083/cpsess##########/execute/Ftp/add_ftp?user=username
When authenticating in cPanel in a browser, the user is redirected to the cPanel home page and the cPanel session id is displayed in the URL.
I am using Apache HTTP client version 4.5.13. I have no problem authenticating using the following code:
HttpHost targetHost = new HttpHost(domain, 2083, "https");
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(AuthScope.ANY,
new UsernamePasswordCredentials(user, password));
AuthCache authCache = new BasicAuthCache();
authCache.put(targetHost, new BasicScheme());
// Add AuthCache to the execution context
HttpClientContext context = HttpClientContext.create();
context.setCredentialsProvider(credsProvider);
context.setAuthCache(authCache);
// disable the redirect
//HttpClient client = HttpClientBuilder.create().disableRedirectHandling().build();
// dont disable the redirect
HttpClient client = HttpClientBuilder.create().build();
HttpResponse response = client.execute(
new HttpGet(url), context);
int statusCode = response.getStatusLine().getStatusCode();
System.out.println(statusCode);
Header[] headers = response.getAllHeaders();
for (Header header : headers) {
System.out.println(header.toString());
}
HttpEntity entity = response.getEntity();
if (entity != null) {
// return it as a String
String result = EntityUtils.toString(entity);
System.out.println(result);
}
However when I print out my headers I do not have a Location header so I can not get the URL that contains the session Id.
If I disable the redirect using the line that is commented out above:
HttpClient client = HttpClientBuilder.create().disableRedirectHandling().build();
Then I do get a Location header. However it only provides me with the end of the URl like:
Location: /frontend/paper_lantern/index.html
I need the full URL like:
https://someURL.com:2083/cpsess3886765014/frontend/paper_lantern/index.html
So that I can get the cPanel session Id (cpsess3886765014) in the above URL.
Any help would be much appreciated. Thanks!
OK I figured this out. I can use the following code:
List<URI> redirectLocations = context.getRedirectLocations();
for (URI uri : redirectLocations){
System.out.println(uri.toASCIIString());
}
And I can get the redirects
I'm trying to hit a REST API link using Apache HttpClient but I keep getting a 401 error returned. I can login when I go to the URL in browser, after being prompted for a password. The code I'm using is below:
CredentialsProvider provider = new BasicCredentialsProvider();
UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(creds.get(0), creds.get(1));
provider.setCredentials(AuthScope.ANY, credentials);
AuthCache authCache = new BasicAuthCache();
authCache.put(new HttpHost(uri.getHost(), uri.getPort(), "https"), new BasicScheme());
BasicHttpContext context = new BasicHttpContext();
context.setAttribute(ClientContext.CREDS_PROVIDER, provider);
context.setAttribute(ClientContext.AUTH_CACHE, authCache);
DefaultHttpClient client = new DefaultHttpClient();
client.setHttpRequestRetryHandler(new DefaultHttpRequestRetryHandler());
client.setCredentialsProvider(provider);
HttpResponse response = null;
try
{
// response = client.execute(new HttpGet(uri));
response = client.execute(new HttpGet(uri), context);
}
catch(IOException e)
{
logger.error("Error running authenticated get request: " + e);
}
I'm using HttpClient 4.2.3 and unfortunately I'm not able to upgrade this.
Any help would be appreciated! Thanks!
EDIT: turns out I need to supply the certificate, like using -cacert in curl, however I can't find an example of this!
Since you need to provide a certificate maybe this can help:
http://hc.apache.org/httpcomponents-client-4.2.x/httpclient/examples/org/apache/http/examples/client/ClientCustomSSL.java
I think that example complies with 4.2.3 .
I use the following command to generate web service client files for java.
wsimport -keep http://test.com/test?wsdl -xauthfile auth.txt
The following was in auth.txt
http://user:password#ip:port//path
But, the password was having special characters like abcw#sdsds.
So I was getting wrong format error. So I have encoded password like abcw%40sdsds. But, now got authentication error due to wrong password because of parsing.
Is there any ways to handle this scenario ?
After checking online I found this bug was actually fixed in the latest version. But I still get the same issue. You can refer to the following links for information on the bug.
https://github.com/javaee/metro-jax-ws/issues/1101
So I finally made custom HTTP request with NTLM authentication using HTTP Client in Java.
String bodyAsString = ""; //Provide Input SOAP Message
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(AuthScope.ANY,
new NTCredentials("UserName", "Password", "Host", "Domain"));
HttpClient client = HttpClientBuilder.create().setDefaultCredentialsProvider(credsProvider).build();
HttpPost post = new HttpPost("URL"); //Provide Request URL
try
{
StringEntity input = new StringEntity(bodyAsString);
input.setContentType("text/xml; charset=utf-8");
post.setEntity(input);
post.setHeader("Content-type", "text/xml; charset=utf-8");
post.setHeader("SOAPAction", ""); //Provide Soap action
org.apache.http.HttpResponse response = client.execute(post);
HttpEntity responseEntity = response.getEntity();
if (responseEntity != null)
{
return EntityUtils.toString(responseEntity);
}
}
I got the above solution from the following github link
https://github.com/sujithtw/soapwithntlm
My problem is i'm trying to get into scopus using a crawler but it requires my crawler to enter the site through my school proxy server. I tried authenticating but it keep responding with 401 status.
public void testConnection() throws ClientProtocolException, IOException {
DefaultHttpClient httpclient = new DefaultHttpClient();
List<String> authpref = new ArrayList<String>();
authpref.add(AuthPolicy.NTLM);
httpclient.getParams().setParameter(AuthPNames.TARGET_AUTH_PREF, authpref);
NTCredentials creds = new NTCredentials("username","password","ezlibproxy1.ntu.edu.sg","ntu.edu.sg");//this is correct
httpclient.getCredentialsProvider().setCredentials(AuthScope.ANY, creds);
HttpHost target = new HttpHost("ezlibproxy1.ntu.edu.sg", 443, "https");//this is correct
// Make sure the same context is used to execute logically related requests
HttpContext localContext = new BasicHttpContext();
// Execute a cheap method first. This will trigger NTLM authentication
HttpGet httpget = new HttpGet("http://www-scopus-com.ezlibproxy1.ntu.edu.sg/authid/detail.url?authorId=14831850700");
HttpResponse response = httpclient.execute(target, httpget, localContext);
HttpEntity entity = response.getEntity();
System.out.println(EntityUtils.toString(entity));
int statusCode = response.getStatusLine().getStatusCode();
System.out.println("Status Code:" + statusCode);
}
The status code respond is 401 (unauthorised).
Any suggestion on this?
I'm trying to access a RESTful web service through the Android Emulator on my PC, which uses a proxy to connect to the internet.
I have code working fine to access the web service on an actual Android device that has its own data connection with the following code:
DefaultHttpClient client = new DefaultHttpClient();
client.getParams().setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true);
HttpGet request = new HttpGet("http://mytesturl.com/services/serviceName");
UsernamePasswordCredentials creds =
new UsernamePasswordCredentials("username", "password");
request.addHeader(BasicScheme.authenticate(creds, "UTF-8", false));
HttpResponse response = client.execute(request);
I've tried a number of approaches to try to get the Emulator to allow connection through the proxy, but none have worked.
Note, I do have the INTERNET enabled in AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />
Attempt 1 - Setting Properties:
This produces an UnknownHostException for the URL of my service at the execute() call
Properties props = System.getProperties();
props.put("http.proxyHost", "httpproxy.mycompany.com");
props.put("http.proxyPort", "80");
Attempt 2 - Setting the proxy in the DefaultHttpClient:
This produces an UnknownHostException for the actual proxy
DefaultHttpClient client = new DefaultHttpClient();
client.getParams().setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true);
HttpHost proxy = new HttpHost("httpproxy.mycompany.com", 80);
client.getCredentialsProvider().setCredentials(
new AuthScope("httpproxy.mycompany.com", 80),
new UsernamePasswordCredentials("username", "password"));
client.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
HttpGet request = new HttpGet("http://mytesturl.com/services/serviceName");
UsernamePasswordCredentials cred =
new UsernamePasswordCredentials("username", "password");
request.addHeader(BasicScheme.authenticate(cred, "UTF-8", false));
HttpResponse response = client.execute(request);
Attempt 3 - Setting the proxy in the HttpGet
This produces an UnknownHostException for the URL in my HttpGet
DefaultHttpClient client = new DefaultHttpClient();
client.getParams().setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true);
HttpGet request = new HttpGet("http://mytesturl.com/services/serviceName");
UsernamePasswordCredentials cred =
new UsernamePasswordCredentials("username", "password");
request.addHeader(BasicScheme.authenticate(cred, "UTF-8", false));
Header bs = new BasicScheme().authenticate(
new UsernamePasswordCredentials("username", "password"),
request);
request.addHeader("Proxy-Authorization", bs.getValue());
HttpResponse response = client.execute(request);
I'm not sure what else to try. I'm open to any suggestions.
Having the same problem, I succeeded with a variation on attempt 3 (code below), the cruicial difference being the setProperty statements. Note that the web service I am calling does not require authentication so I'm only setting the proxy authorization header.
System.setProperty("java.net.useSystemProxies", "false");
System.setProperty("http.proxyHost", "123.56.7.9");
System.setProperty("http.proxyPort", "8080");
DefaultHttpClient client = new DefaultHttpClient();
client.getParams().setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true);
HttpGet request = new HttpGet("web service url");
Header bs = new BasicScheme().authenticate(
new UsernamePasswordCredentials("NETWORKID", "netpassword"),
request);
request.addHeader("Proxy-Authorization", bs.getValue());
HttpResponse response = client.execute(request);
did you use -http-proxy http://: emulator command line option or "Settings" -> "Wireless & Networks" -> "Mobile Networks" -> "Access Point Names" -> "Telkila" or Home > Menu > Settings > Wireless Controls > Mobile Networks > Access Point Names?