I need to be able to set a system property in a Mobilefirst Java adapter (7.1). When I do add it, it seems to have no effect as it does in a stand-alone java app in eclipse. Any ideas on how to get the same function?
UPDATE: I apologize...should have added code sample....
You can see which setProperties I am referring to below....neither seem to take affect. The first one should dump out a bunch of debug info...second one will not print anything...but will fix another issue with TLSv1.2.
public String getHTTPRequest(String baseURL, String authHeader) {
logger.info("In getHTTPRequest");
logger.info("Parms: URL = " + baseURL + " auth = " + authHeader);
System.setProperty("javax.net.debug", "ssl:handshake:verbose");
System.setProperty("jsse.enableSNIExtension", "false");
String json = "";
try {
SSLContext context = SSLContext.getInstance("TLSv1.2");
context.init(null, null, null);
SSLConnectionSocketFactory sslCF = new SSLConnectionSocketFactory(context, new HostnameVerifier() {
#Override
public boolean verify(String hostname, SSLSession session) {
// or add your own test here
return true;
}
});
//CloseableHttpClient httpClient = HttpClientBuilder.create().setSSLSocketFactory(sslCF).build();
HttpClientBuilder clientBuilder = HttpClientBuilder.create().setSslcontext(context);
CloseableHttpClient httpClient = clientBuilder.build();
HttpGet request = new HttpGet(new URI(baseURL));
request.addHeader("Authorization", authHeader);
CloseableHttpResponse httpResponse = httpClient.execute(request);
json = EntityUtils.toString(httpResponse.getEntity());
System.out.println(" Response = " + json);
} catch (Exception e) {
logger.info(" Exception in getHTTPRequest = " + e.toString());
}
return json;
}
Solution from the comments section:
I added the set property value to the jvm.options file and that seemed to work....-Djsse.enableSNIExtension=false
Related
I need to write a Cucumber Test case to verify if a website supports 2-way SSL in Java. I'm not sure how to exactly do it after countlessly reading through different articles and answers. I've generated a self signed certificate for the client side of the test case, and I add it in the request, but I'm not sure how exactly to verify that the website I'm accessing supports 2-way SSL. This is my code so far that I've gotten from using different bits of answers and articles online.
org.apache.log4j.BasicConfigurator.configure();
try {
String CERT_PASSWORD = "somePass";
KeyStore identityKeyStore = KeyStore.getInstance("jks");
FileInputStream identityKeyStoreFile = new FileInputStream(new File(System.getProperty("user.dir") + "/src/main/resources/files-for-testcases/ultimate.jks"));
identityKeyStore.load(identityKeyStoreFile, CERT_PASSWORD.toCharArray());
SSLContext sslContext = SSLContexts.custom()
// load identity keystore
.loadKeyMaterial(identityKeyStore, CERT_PASSWORD.toCharArray(), (aliases, socket) -> "bddsecurity")
.build();
SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext,
new String[]{"TLSv1.2", "TLSv1.1"},
null,
SSLConnectionSocketFactory.getDefaultHostnameVerifier());
CloseableHttpClient client = HttpClients.custom()
.setSSLSocketFactory(sslConnectionSocketFactory)
.build();
// Call a SSL-endpoint
return callEndPoint (client, url);
} catch (Exception ex) {
System.out.println("Boom, we failed: " + ex);
ex.printStackTrace();
}
return 404;
}
private static int callEndPoint (CloseableHttpClient aHTTPClient, String aEndPointURL) {
try {
HttpGet httpGet = new HttpGet(aEndPointURL);
LOG.info("**GET** request Url: " + httpGet.getURI());
HttpResponse response = aHTTPClient.execute(httpGet);
int responseCode = response.getStatusLine().getStatusCode();
LOG.info("Response Code: " + responseCode);
return responseCode;
} catch (Exception ex) {
System.out.println("Boom, we failed: " + ex);
ex.printStackTrace();
}
return 404;
}
So just to update, the issue was with my server that was alright with connections that didn't have a certificate. It wasn't, and then my application threw an error but the diagnosis was straightforward and it now is all good.
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();
When I execute an API through following method, I always get 404 as response code.
private void execute() throws IllegalStateException, IOException, NoSuchAlgorithmException {
Map<String, String> comment = new HashMap<String, String>();
comment.put("accounts-groups", "customers/enterprise");
comment.put("companyType", "customer");
comment.put("companyName", "Test");
String json = new GsonBuilder().create().toJson(comment, Map.class);
Log.i(TAG, "json : "+json);
HttpResponse response = makeRequest(URL, json);
/*Checking response */
if(response != null) {
InputStream inputStream = response.getEntity().getContent(); //Get the data in the entity
int statusCode = response.getStatusLine().getStatusCode();
Log.i(TAG, "statusCode : "+statusCode);
String result;
// convert inputstream to string
if(inputStream != null)
result = convertStreamToString(inputStream);
else
result = "Did not work!";
Log.i(TAG, "result : "+result);
}
}
private HttpResponse makeRequest(String uri, String json) throws NoSuchAlgorithmException {
Log.i(TAG, "uri : "+uri);
try {
HttpPost httpPost = new HttpPost(uri);
httpPost.setEntity(new StringEntity(json, HTTP.UTF_8));
long timestamp = System.currentTimeMillis();
String signatureKey = PRIVATE_KEY + timestamp;
byte[] bytesOfMessage = signatureKey.getBytes(HTTP.UTF_8);
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] thedigest = md.digest(bytesOfMessage);
char[] signature = Hex.encodeHex(thedigest);
String finalSignature = String.valueOf(signature);
Log.i(TAG, "finalSignature : "+finalSignature);
httpPost.setHeader("Timestamp", ""+timestamp);
httpPost.setHeader("Api_token", API_TOKEN);
httpPost.setHeader("Signature" , finalSignature);
httpPost.setHeader("Accept", "application/json");
httpPost.setHeader(HTTP.CONTENT_TYPE, "application/json");
return new DefaultHttpClient().execute(httpPost);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
I am not getting where am I going wrong. Can anybody please help me out?
from wiki:
The 404 or Not Found error message is a HTTP standard response code
indicating that the client was able to communicate with the server,
but the server could not find what was requested.
so, your code is OK, but server cannot find resource you are looking for. Double check if your url is correct.
how to pass request through fiddler proxy for debugging purposes:
HttpParams params = new BasicHttpParams();
// ....
HttpHost proxy = new HttpHost("192.168.1.12", 8888); // IP to your PC with fiddler proxy
params.setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
// use params as a second parameter to: following constructor:
// public DefaultHttpClient (ClientConnectionManager conman, HttpParams params)
I was getting 404 for POST requests because mod_headers module of Apache 2 server was not enabled. If that happens you can enable it with:
sudo a2enmod headers
and then restart apache:
sudo service apache2 restart
I am trying to send a string from one application to another. I would be returning a response which is a string. Here, myhost.com/views is the 2nd application where I need to send the string value and get a response from it. But when I am trying to send it is not executing this code. Can someone please correct me where I am wrong?
Below is the code I have written.
public static void sendData(String strval) throws IOException{
String doSend="https://myhost.com/views?strval="+strval;
HttpClient httpclient = new DefaultHttpClient();
try {
System.out.println("inside try");
URIBuilder builder = new URIBuilder();
System.out.println("builder="+builder);
builder.setHost("myhost.com").setPath("/views");
builder.addParameter("strval", strval);
System.out.println("add param,sethost,setpath complete");
URI uri = builder.build();
System.out.println("uri="+uri);
HttpGet httpget = new HttpGet(uri);
System.out.println("httpGet"+httpget);
HttpResponse response = httpclient.execute(httpget);
System.out.println(response.getStatusLine().toString());
if (response.getStatusLine().getStatusCode() == 200) {
String responseText = EntityUtils.toString(response.getEntity());
System.out.println("responseText="+responseText);
httpclient.getConnectionManager().shutdown();
} else {
System.out.println("Server returned HTTP code "
+ response.getStatusLine().getStatusCode());
}
} catch (java.net.URISyntaxException bad) {
System.out.println("URI construction error: " + bad.toString());
}
catch(Exception e){ System.out.println("e.getMessage=>"+e.getMessage()); }
}
Code runs till and when I print the exceptions I see excep.getMessage() ->
java.lang.IllegalStateException: Target host must not be null, or set in parameters.
at org.apache.http.impl.client.DefaultRequestDirector.determineRoute(DefaultRequestDirector.java:789)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:414)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:784)
This code is not able to recognize it as a valid URI since it was missing http. This is what I added to resolve the code:
builder.setScheme("http");
I would like to migrate from Commons HttpClient (3.x) to HttpComponents Client (4.x) but having difficulty how to handle redirects. The code works properly under Commons HttpClient but breaks when migrated to HttpComponents Client. Some of the links get undesirable redirects but when I set "http.protocol.handle-redirects" to 'false' a large number links stop working altogether.
Commons HttpClient 3.x:
private static HttpClient httpClient = null;
private static MultiThreadedHttpConnectionManager connectionManager = null;
private static final long MAX_CONNECTION_IDLE_TIME = 60000; // milliseconds
static {
//HttpURLConnection.setFollowRedirects(true);
CookieManager manager = new CookieManager();
manager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
CookieHandler.setDefault(manager);
connectionManager = new MultiThreadedHttpConnectionManager();
connectionManager.getParams().setDefaultMaxConnectionsPerHost(1000); // will need to set from properties file
connectionManager.getParams().setMaxTotalConnections(1000);
httpClient = new HttpClient(connectionManager);
}
/*
* Retrieve HTML
*/
public String fetchURL(String url) throws IOException{
if ( StringUtils.isEmpty(url) )
return null;
GetMethod getMethod = new GetMethod(url);
HttpClient httpClient = new HttpClient();
//configureMethod(getMethod);
//ObjectInputStream oin = null;
InputStream in = null;
int code = -1;
String html = "";
String lastModified = null;
try {
code = httpClient.executeMethod(getMethod);
in = getMethod.getResponseBodyAsStream();
//oin = new ObjectInputStream(in);
//html = getMethod.getResponseBodyAsString();
html = CharStreams.toString(new InputStreamReader(in));
}
catch (Exception except) {
}
finally {
try {
//oin.close();
in.close();
}
catch (Exception except) {}
getMethod.releaseConnection();
connectionManager.closeIdleConnections(MAX_CONNECTION_IDLE_TIME);
}
if (code <= 400){
return html.replaceAll("\\s+", " ");
} else {
throw new Exception("URL: " + url + " returned response code " + code);
}
}
HttpComponents Client 4.x :
private static HttpClient httpClient = null;
private static HttpParams params = null;
//private static MultiThreadedHttpConnectionManager connectionManager = null;
private static ThreadSafeClientConnManager connectionManager = null;
private static final int MAX_CONNECTION_IDLE_TIME = 60000; // milliseconds
static {
//HttpURLConnection.setFollowRedirects(true);
CookieManager manager = new CookieManager();
manager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
CookieHandler.setDefault(manager);
connectionManager = new ThreadSafeClientConnManager();
connectionManager.setDefaultMaxPerRoute(1000); // will need to set from properties file
connectionManager.setMaxTotal(1000);
httpClient = new DefaultHttpClient(connectionManager);
// HTTP parameters stores header etc.
params = new BasicHttpParams();
params.setParameter("http.protocol.handle-redirects",false);
}
/*
* Retrieve HTML
*/
public String fetchURL(String url) throws IOException{
if ( StringUtils.isEmpty(url) )
return null;
InputStream in = null;
//int code = -1;
String html = "";
// Prepare a request object
HttpGet httpget = new HttpGet(url);
httpget.setParams(params);
// Execute the request
HttpResponse response = httpClient.execute(httpget);
// The response status
//System.out.println(response.getStatusLine());
int code = response.getStatusLine().getStatusCode();
// Get hold of the response entity
HttpEntity entity = response.getEntity();
// If the response does not enclose an entity, there is no need
// to worry about connection release
if (entity != null) {
try {
//code = httpClient.executeMethod(getMethod);
//in = getMethod.getResponseBodyAsStream();
in = entity.getContent();
html = CharStreams.toString(new InputStreamReader(in));
}
catch (Exception except) {
throw new Exception("URL: " + url + " returned response code " + code);
}
finally {
try {
//oin.close();
in.close();
}
catch (Exception except) {}
//getMethod.releaseConnection();
connectionManager.closeIdleConnections(MAX_CONNECTION_IDLE_TIME, TimeUnit.MILLISECONDS);
connectionManager.closeExpiredConnections();
}
}
if (code <= 400){
return html;
} else {
throw new Exception("URL: " + url + " returned response code " + code);
}
}
I won't want redirects but under HttpClient 4.x if I enable redirects then I get some that are undesirable, e.g. http://www.walmart.com/ => http://mobile.walmart.com/. Under HttpClient 3.x no such redirects happens.
What do I need to do to migrate HttpClient 3.x to HttpClient 4.x without breaking the code?
It is not the issue with HttpClient 4.x, might be the way target server handle the request, since the user agent is httpclient, it may be handled as mobile (target server may consider other than available browsers like, i.e, chrome, mozilla etc as mobile.)
Please use below code to set it manually
httpclient.getParams().setParameter(
org.apache.http.params.HttpProtocolParams.USER_AGENT,
"Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2"
);