I'm writing a Java program that connects to a web server (HTTPS and requires username/password) with this code, but it hangs when it reaches the execute call:
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
FileInputStream instream = new FileInputStream(new File("D:/jssecacerts"));
try {
trustStore.load(instream, "certspassword".toCharArray());
} finally {
try { instream.close(); } catch (Exception ignore) {}
}
SSLSocketFactory socketFactory = new SSLSocketFactory(trustStore);
Scheme sch = new Scheme("https", 443, socketFactory);
httpclient.getConnectionManager().getSchemeRegistry().register(sch);
HttpGet httpget = new HttpGet("https://server/path/default.aspx");
httpclient.getCredentialsProvider().setCredentials(
new AuthScope("server", 443),
new UsernamePasswordCredentials("user", "pass"));
System.out.println("executing request" + httpget.getRequestLine());
HttpResponse response = httpclient.execute(httpget);
This is what I've tried in order to isolate the problem:
If I comment out the setCredentials line, it doesn't hang and the server instantly returns a HTTP/1.1 401 Unauthorized response
It doesn't matter if I provide a valid username/password or not
I've tried to specify timeouts with different methods but it remains hung after the timeout interval is over
Related
I wrote a little programm, that reads an XML-File via http-get.
Loacally it's running fine.
But on the server it keeps breaking without any exception, except a nullpointer because of the empty result
I'm using the apache http lib.
Here is the class, i added the numbers, to track the exact point, where it stops working.
public void get(String url, String user, String pass, File outfile) throws IOException
{
log.info("1");
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM, "basic"),
new UsernamePasswordCredentials(user, pass));
log.info("2");
CloseableHttpClient httpClient = HttpClients.custom().setDefaultCredentialsProvider(credsProvider).build();
HttpResponse response = null;
log.info("6");
InputStream content = null;
FileOutputStream outputStream = null;
try
{
HttpGet httpGet = new HttpGet(url);
log.info("3");
httpGet.addHeader("Content-Type", "text/xml");
log.info("4");
httpGet.addHeader("Accept", "text/xml");
log.info("5");
log.info("6");
log.info("7");
outputStream = new FileOutputStream(outfile);
log.info("8");
response = httpClient.execute(httpGet);
log.info("9");
log.info("response: {}", response);
log.info("10");
content = response.getEntity().getContent();
log.info("11");
log.info("content: {}", content);
log.info("12");
IOUtils.copy(content, outputStream);
log.info("13");
}
catch (Exception e)
{
log.error("", e);
}
finally
{
try
{
log.info("14");
log.info(String.valueOf(content));
content.close();
outputStream.close();
}
catch (IOException e)
{
log.error("Error while closing Streams", e);
}
}
}
Here are the log snipets; I tried to mask every sensible data and i hope i didn't miss anything
Local log snipet
Remote log snipet
As you can see, the numbers stop after 8 and start in the finally block again with 14. the rest is missing and I have no idea, why.
The used URL is reachable via browser or comandline.
The problem is a bit tricky: you are running into some sort of Error here. Probably NoClassDefFoundError or something alike.
But as you are catching for Exception this piece of code simply doesn't "see" the real problem.
So to debug the problem: either check the server log files or change your code to catch Throwable instead of Exception.
I am implementing a proxy server which will be used to security purposes, and I am implementing it in Java, using Httpclient and native Sockets. The problem comes out when using SSL connections and even normal connections, because the browswer alaways detects it as XXS/cross side scripting threats.
The main code I am using to make the traffic flow is:
HttpResponse response = null;
try {
SSLSocketFactory sf = new SSLSocketFactory(acceptingTrustStrategy,
SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("https", socket.getPort(), sf));
ClientConnectionManager ccm = new PoolingClientConnectionManager(registry);
DefaultHttpClient httpClient = new DefaultHttpClient(ccm);
httpClient.getConnectionManager().getSchemeRegistry().register(
new Scheme("https", 443, SSLSocketFactory.getSystemSocketFactory())
);
if (!urlToCall.contains("http://") || !urlToCall.contains("https://")) {
urlToCall = "https://" + urlToCall;
}
HttpGet getMethod = new HttpGet(urlToCall);
response = httpClient.execute(getMethod);
} finally {
}
InputStream is = null;
if (response.getStatusLine().getStatusCode() == 200 && response != null) {
try {
is = response.getEntity().getContent();
out.writeBytes(inputStreamToString(is));
} catch (IOException ioe) {
ProxyThread.LOGGER.debug(ProxyThread.LOGGER.getName(), ioe);
} finally {
rd.close();
}
}
Is there anyone with good idea for making traffic flow with SSL or NOT?
i'm trying to send a https request through a proxy with apache httpclient,but i can't find the headers on the proxy side
HttpClient httpClient =new DefaultHttpClient();
HttpHost proxy = new HttpHost("10.1.1.100", 8080);
httpClient.getParams().setParameter(ConnRouteParams.DEFAULT_PROXY,proxy);
HttpGet get = new HttpGet(uri);
get.addHeader("Proxy-Authorization", "222222");
HttpResponse hr = defaultHttpClient.execute(get);
the proxy side only find proxy-connection and user-agent:
Proxy-Connection:[Keep-Alive] User-Agent:[Apache-HttpClient/4.3.6 (java 1.5)]
First, that's not how you authenticate to a proxy. Second, those headers are added to the get request (not to the proxy). Finally, this is based on an example the HttpClient examples - specifically ClientProxyAuthentication and updated to use try-with-resources (and modified to use an URL)
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(new AuthScope("10.1.1.100", 8080),
new UsernamePasswordCredentials("username", "password"));
try (CloseableHttpClient httpclient = HttpClients.custom()
.setDefaultCredentialsProvider(credsProvider).build()) {
URL url = new URL(uri);
HttpHost target = new HttpHost(url.getHost(), url.getPort(),
url.getProtocol());
HttpHost proxy = new HttpHost("10.1.1.100", 8080);
RequestConfig config = RequestConfig.custom().setProxy(proxy)
.build();
HttpGet httpget = new HttpGet(url.getPath());
httpget.setConfig(config);
System.out.println("Executing request " + httpget.getRequestLine()
+ " to " + target + " via " + proxy);
try (CloseableHttpResponse response = httpclient.execute(target,
httpget)) {
System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
EntityUtils.consume(response.getEntity());
}
} catch (IOException e1) {
e1.printStackTrace();
}
I'm working on a Java program that will send POST requests to a website for my company to use. We do not own this website, they are separate from us. I've been fighting with various ways to actually pass it the very picky parameters it wants in order for me to do work on it from a program (as opposed to doing it manually).
I've found that the Apache HttpClient 4.3 seems to be my best route for actually trying to access it, anything results in a angry response from the website telling me my username and password and not valid/authorized.
But then I got an error because the site certificate doesn't match, I contacted their support and they reportedly share an infrastructure with another site so the certificate mismatch is expected.
So I went commandline and generated a keystore, passed that to the program and then got the error "java.security.cert.CertificateException: No subject alternative DNS name matching".
Some hunting lead me to utilize a verifier, which removed errors.
Then I realized that I can't make URLConnection/HttpsURLConnection and HttpClient/HttpPost work together. That's where I'm stuck. I'm not sure how to make the code that handles my keystore, TrustManager, SSLSocketFactory, etc connect to the part where I actually have to connect and POST.
Code that handles the certificates and verification:
InputStream in = new FileInputStream(new File("C:\\Program Files (x86)\\Java\\jre7\\bin\\my.keystore"));
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(in, "blahblah".toCharArray());
in.close(); TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ks);
X509TrustManager defaultTrustManager = (X509TrustManager)tmf.getTrustManagers()[0];
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, new TrustManager[] {defaultTrustManager}, null);
javax.net.ssl.SSLSocketFactory sslSocketFactory = context.getSocketFactory();
URL url = new URL("https://emailer.driveclick.com/dbadmin/xml_post.pl");
URLConnection con = url.openConnection();
((HttpsURLConnection) con).setSSLSocketFactory(sslSocketFactory);
((HttpsURLConnection) con).setHostnameVerifier(new Verifier());
con.connect();
in = con.getInputStream();
Code that should be connecting me to the website:
try {
//log into the website
String url2 = "https://emailer.driveclick.com/dbadmin/xml_post.pl";
HttpClient client = HttpClientBuilder.create().build();
HttpPost post = new HttpPost(url2);
post.setHeader("User-Agent", USER_AGENT);
List<BasicNameValuePair> urlParameters = new ArrayList<>();
urlParameters.add(new BasicNameValuePair("username", "namefoo"));
urlParameters.add(new BasicNameValuePair("api_password", "passfoo"));
post.setEntity(new UrlEncodedFormEntity(urlParameters));
org.apache.http.HttpResponse response = client.execute(post);
System.out.println("\nSending 'POST' request to URL : " + url2);
System.out.println("Post parameters : " + post.getEntity());
System.out.println("Response Code : " + response.getStatusLine().getStatusCode());
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer result = new StringBuffer();
String line = "";
while ((line = rd.readLine()) != null)
{
result.append(line);
}
System.out.println(result.toString());
} catch (UnsupportedEncodingException ex) {
Logger.getLogger(LastFileMove.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(LastFileMove.class.getName()).log(Level.SEVERE, null, ex);
}
EDIT: I forgot to include the little class I made for the Verifier that I referenced.
public class Verifier implements HostnameVerifier
{
public boolean verify(String arg0, SSLSession arg1) {
return true; // mark everything as verified
}
}
Update 5/8/2014
SSLConext and Verifier are now set up like this:
SSLContext sslContext = SSLContexts.custom()
.useTLS()
.loadTrustMaterial(ks)
.build();
X509HostnameVerifier verifier = new AbstractVerifier()
{
#Override
public void verify(final String host, final String[]
cns, final String[] subjectAlts) throws SSLException
{
verify(host, cns, subjectAlts, true);
}
};
And I've gone ahead and changed my HttpClient to a closeable one here:
CloseableHttpClient client = HttpClients.custom()
sslSocketFactory)
.setHostnameVerifier(verifier)
.setSslcontext(sslContext)
.build();
And I'm back to having "javax.net.ssl.SSLException: hostname in certificate didn't match" errors. Suggestions?
I have no idea how Verifier is implemented but this code snippet demonstrates how one can create a custom hostname verifier none of those shipped with HttpClient fits their needs
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream in = new FileInputStream(new File("C:\\Program Files (x86)\\Java\\jre7\\bin\\my.keystore"));
try {
ks.load(in, "blahblah".toCharArray());
} finally {
in.close();
}
SSLContext sslContext = SSLContexts.custom()
.useTLS()
.loadTrustMaterial(ks)
.build();
X509HostnameVerifier verifier = new AbstractVerifier() {
#Override
public void verify(final String host, final String[] cns, final String[] subjectAlts) throws SSLException {
verify(host, cns, subjectAlts, true);
}
};
CloseableHttpClient hc = HttpClients.custom()
.setSslcontext(sslContext)
.setHostnameVerifier(verifier)
.build();
I am trying to setup 2 - way SSL between client and server using HttpClient 4.3.3 library for a WebApp to communicate with a server component.
I have the client / server commuicating successfully over SSL in what I believe looks to be one-way SSL in that the CA hierarchy is not being strictly validated from what I can see, or maybe HttpClient is hiding all the details. It also seems quite difficult to get the peer certificate chain, this seems to be accessible through SSLSession object which would be present in strict JSSE interaction but HttpClient abstracts away from and does not seem possible to access?
Looking at the debug SSL logging it all seems to be fine, I guess i just wanted to confirm that 2 way SSL is happening even if it is happening within HttpClient.
Also, the TrustStrategy only seems to access the client Certificate chain and regardless of true or false returned for 'isTrusted' never seems to behave differently.
TLDR; is this 2 way SSL, if not what needs to change? How does one get access to peer certificate chain using HttpClient? Does the TrustStrategy actually do anything?
This is my code thus far which works with the server which I know to be running SSL:
try{
KeyStore trustStore = KeyStore.getInstance(keystoreType, keystoreProvider);
FileInputStream instream = new FileInputStream(new File("/path/to/keystore"));
try {
trustStore.load(instream,keystorePassword.toCharArray());
} finally {
instream.close();
}
//establish trust strategy
TrustStrategy trustStrategy = new TrustStrategy() {
#Override
public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
for(X509Certificate cert : x509Certificates){
System.out.println("cert = " + cert);
}
return true;
}
};
SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(trustStore, keystorePassword.toCharArray())
.loadTrustMaterial(trustStore, trustStrategy).build();
// Allow TLSv1 protocol only
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sslcontext,
new String[] { "TLSv1" },
null,
SSLConnectionSocketFactory.STRICT_HOSTNAME_VERIFIER);
CloseableHttpClient httpclient = HttpClients.custom()
.setSSLSocketFactory(sslsf)
.build();
try {
HttpPost post = new HttpPost(existingSSLServerURL);
HttpEntity requestEntity = new ByteArrayEntity(sampleAuthenticationForSSL.getBytes("UTF-8"));
post.setEntity(requestEntity);
System.out.println("executing request" + post.getRequestLine());
CloseableHttpResponse response = httpclient.execute(post);
try {
HttpEntity entity = response.getEntity();
System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
if (entity != null) {
System.out.println("Response content length: " + entity.getContentLength());
BufferedReader in = new BufferedReader(new InputStreamReader(entity.getContent()));
String inputline = null;
while((inputline = in.readLine()) != null){
System.out.println(inputline);
}
}
EntityUtils.consume(entity);
} finally {
response.close();
}
} finally {
httpclient.close();
}
}catch(Exception e){
e.printStackTrace();
fail();
}