I've written code to download some data from external server. The server is using self-signed certificate, need to have session cookie set and some POST data. Currently I have the following code:
private byte[] getResponse(URL url, String postData)
throws IOException, KeyManagementException, CertificateException, KeyStoreException,
NoSuchAlgorithmException
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.setRequestProperty("User-Agent", userAgent);
urlConnection.setRequestProperty("Cookie", cookie);
urlConnection.setRequestMethod("POST");
urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);
urlConnection.setSSLSocketFactory(getSocketFactory());
OutputStream os = urlConnection.getOutputStream();
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(os, "UTF-8"));
writer.write(postData);
writer.flush();
writer.close();
os.close();
try {
urlConnection.connect();
InputStream is = urlConnection.getInputStream();
int len = 0;
while ((len = is.read(buffer)) != -1)
{
baos.write(buffer, 0, len);
}
}
catch(IOException e)
{
throw e;
}
finally {
urlConnection.disconnect();
}
return baos.toByteArray();
}
On Ice Cream Sandwich and higher (API >= 14) everything works fine. The problem started when I tried to make the app work on API >= 8. It is now properly sending the request with GET and no params (CAPTCHA) but when it comes to getting the actual data urlConnection's connect method fails with no exception. The code for getSocketFactory() is:
private SSLSocketFactory getSocketFactory()
throws CertificateException, IOException, KeyStoreException, NoSuchAlgorithmException,
KeyManagementException
{
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = context.getResources().openRawResource(R.raw.historiapojazdu);
Certificate ca;
try {
ca = cf.generateCertificate(caInput);
} finally {
caInput.close();
}
// Create a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
// Create an SSLContext that uses our TrustManager
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
return context.getSocketFactory();
}
EDIT: I've just realized that connect method apparently worked but it didn't follow redirect on the response so input stream was always empty.
I've just figured it myself. It looks like HttpsUrlConnection simply does not follow redirects on API 10 and lower for some reason even despite implicitly calling setInstanceFollowRedirects(true). It is just ignoring that setting. I've worked that around with this code just after calling urlConnection.connect():
String redirect = urlConnection.getHeaderField("Location");
if(redirect != null) //truth before ICS
{
urlConnection.disconnect();
urlConnection = (HttpsURLConnection) (new URL(redirect)).openConnection();
urlConnection.setRequestProperty("User-Agent", userAgent);
urlConnection.setRequestProperty("Cookie", cookie);
urlConnection.setRequestMethod("POST");
urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);
urlConnection.setSSLSocketFactory(getSocketFactory());
OutputStream os2 = urlConnection.getOutputStream();
BufferedWriter writer2 = new BufferedWriter(
new OutputStreamWriter(os2, "UTF-8"));
writer2.write(postData);
writer2.flush();
writer2.close();
os2.close();
urlConnection.connect();
}
Related
I'm in a Spring boot service, that will be within a microservice, attempting to connect to an external SOAP Web Service, that requires a cert that was created by that service and a password. This is being written in Windows, but will need to be run on Unix. Right now, I've hardcoded some things for Windows. This is what I have coded for my side, but I'm getting an error on httpConn.getInputStream():
"sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target".
Can someone help me understand what I'm missing?
public String getSoapData(String contentType) throws IOException, NoSuchAlgorithmException, KeyManagementException, CertificateException, KeyStoreException {
StringBuilder retVal = new StringBuilder();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
// get user password and file input stream
char[] password = "MYPass".toCharArray();
java.io.FileInputStream fis = null;
//X509Certificate caCert = null;
//CertificateFactory cf = CertificateFactory.getInstance("X.509");
try {
fis = new java.io.FileInputStream("C:\\MyCerts\\dev_HubExplorer1.pfx");
ks.load(fis, password);
//caCert = (X509Certificate)cf.generateCertificate(fis);
//ks.setCertificateEntry("caCert", caCert);
} catch (Exception e) {
Common.screenPrint("Exception while importing certificate:%s%s", Common.CRLF, e.getMessage());
} finally {
if (fis != null) {
fis.close();
}
}
tmf.init(ks);
//TODO (GWL) Need to get this from a configuration file/db.
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(null, tmf.getTrustManagers(), new java.security.SecureRandom());
URL url = new URL(_publicRecordURL);
HttpsURLConnection httpConn = (HttpsURLConnection) url.openConnection();
httpConn.setSSLSocketFactory(sslContext.getSocketFactory());
byte[] bytes = _requestTemplate.getBytes();
// Set the appropriate HTTP parameters.
httpConn.setRequestProperty("Content-Length", String.valueOf( bytes.length ) );
httpConn.setRequestProperty("Content-Type","text/xml; charset=utf-8");
httpConn.setRequestProperty("SOAPAction",_soapAction);
httpConn.setRequestProperty("Accept","text/xml");
httpConn.setRequestMethod( "POST" );
httpConn.setDoOutput(true);
httpConn.setDoInput(true);
//Everything's set up; send the XML that was read in to b.
OutputStreamWriter writer = new OutputStreamWriter(httpConn.getOutputStream());
writer.write(_requestTemplate);
writer.flush();
//Read the response and write it to standard out.
InputStreamReader isr = new InputStreamReader(httpConn.getInputStream());
BufferedReader in = new BufferedReader(isr);
String inputLine;
while ((inputLine = in.readLine()) != null) {
retVal.append(inputLine + Common.CRLF);
System.out.println(inputLine);
}
in.close();
return retVal.toString();
}
you can follow this stackoverflow answer to get the solution of this problem :
https://stackoverflow.com/a/12146838/7801800
I have .p12 certificate file which needs to be included in every sent to server from my java code.
When i run sample code from linux its gives me exception
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: timestamp check failed
My java code is below :
HttpsURLConnection con = null;
try
{
System.out.println("Calling webservice ..... ");
char[] passw = "mypassword".toCharArray();
KeyStore ks = KeyStore.getInstance("PKCS12");
InputStream keyInput = new FileInputStream( "/usr/local/KEYSTORE.p12");
ks.load(keyInput, passw );
keyInput.close();
System.out.println("Reading certificate file Completed");
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, passw);
System.out.println("Set SSL certificate");
SSLContext sclx = SSLContext.getInstance("SSL");
sclx.init( kmf.getKeyManagers(), null, new SecureRandom());
SSLContext.setDefault(sclx);
HttpsURLConnection.setDefaultSSLSocketFactory(sclx.getSocketFactory());
URL url = new URL("https://myurl.server.com");
con = (HttpsURLConnection)url.openConnection();
System.out.println("Connection successfull");
//con.setSSLSocketFactory(sclx.getSocketFactory());
System.out.println("Token Id 026F800E-562D-4B0F-BC56-AC16895072F4");
if(con!=null)
{
System.out.println("Inside connection");
con.setRequestProperty("Content-Type","application/json;charset=utf-8");
con.setRequestProperty("Accept", "application/json");
con.setRequestProperty("Accept-Charset", "UTF-8");
con.setRequestProperty("Token-Id","026F800E-562D-4B0F-BC56-AC16895072F4");
con.setDoOutput(true);
con.setDoInput(true);
con.setUseCaches(false);
con.setDefaultUseCaches(false);
con.setRequestMethod("POST");
con.connect();
OutputStreamWriter os = new OutputStreamWriter(con.getOutputStream(), "UTF-8");
os.write("request String");
os.flush();
os.close();
InputStreamReader dis = new InputStreamReader(con.getInputStream(),"UTF-8");
if (null != dis)
{
System.out.println("Reading response from webservice 1");
BufferedReader reader = new BufferedReader(dis);
String line;
while((line = reader.readLine()) != null) {
System.out.println(line);
}
}
}
}
catch(IOException ioex)
{
System.err.println("Exception : "+ioex);
e.printStackTrace();
}
catch(Exception ex){
ex.printStackTrace();
}
finally{
if(con != null) {
con.disconnect();
}
}
Its work on windows server but gives exception on linux server.
Please any one help me to resolved this.
I have a problem with my Android Phonegap App.
I created a plugin to send Data from HTML/JAVASCRIPT to Java and Java will send this DATA to a
Server with HTTPS post.
To get this Worke I need to Open a ssl.crt (certification) from my Asset folder.
In the Cordova Class this function dose work because it extends the CordovaActivity.
My Plugin Class : public class ConnectPlugin extends CordovaPlugin
Here is the Login method:
protected String tryLogin_2(String d1) throws CertificateException, FileNotFoundException, IOException, KeyStoreException, NoSuchAlgorithmException, KeyManagementException
{
// Load CAs from an InputStream
// (could be from a resource or ByteArrayInputStream or ...)
CertificateFactory cf = CertificateFactory.getInstance("X.509");
// From https://www.washington.edu/itconnect/security/ca/load-der.crt
InputStream caInput = new BufferedInputStream(this.getAssets().open("ssl.crt"));
java.security.cert.Certificate ca;
try {
ca = cf.generateCertificate(caInput);
} finally {
caInput.close();
}
// Create a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
// Create an SSLContext that uses our TrustManager
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
String httpsURL = "https://URL.com";
OutputStreamWriter request = null;
DataInputStream response_2 = null;
String parameters = "1="+d1;
String response = null;
try
{
URL myurl = new URL(httpsURL);
HttpsURLConnection con = (HttpsURLConnection)myurl.openConnection();
con.setSSLSocketFactory(context.getSocketFactory());
con.setRequestMethod("POST");
con.setRequestProperty("Content-length", String.valueOf(query.length()));
con.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
con.setDoOutput(true);
con.setDoInput(true);
request = new OutputStreamWriter(con.getOutputStream());
request.write(parameters);
request.flush();
request.close();
String line = "";
InputStreamReader isr = new InputStreamReader(con.getInputStream());
BufferedReader reader = new BufferedReader(isr);
StringBuilder sb = new StringBuilder();
while ((line = reader.readLine()) != null)
{
sb.append(line + "\n");
}
//Response from server after login process will be stored in response variable.
response = sb.toString();
isr.close();
reader.close();
}
catch(IOException e)
{
response = "Error"; // Error
}
return response;
}
The problem now is "The method getAssets() is undefined for the type ConnectPlugin".
I can't use the getAssets() method outside the Main Class.
In my MainClass the obove code work 100% fine and sends a request to my server.
But not in my Plugin Class.
Use
cordova.getActivity().getAssets().open("ssl.crt"));
I'm trying to download a zip file from an url but the url returns a 404 page with the app.
When I try with firefox, it just asked the keystore so I put it and it works : I can download the ZIP file.
I don't really understand what I'm doing wrong.
Here is my code
URL url = new URL(reportInfo.getURI().toString());
HttpsURLConnection con = (HttpsURLConnection) url
.openConnection();
/*
* Keystore manager
*/
KeyManagerFactory keyManagerFactory = KeyManagerFactory
.getInstance("SunX509");
String pKeyPassword = GSBConstants.KEYSTORE_PASSWORD;
KeyStore keyStore = KeyStore.getInstance("JKS");
InputStream keyInput = new FileInputStream(new File(
cc.getWorkingDir() + File.separator
+ GSBConstants.KEYSTOREJKS_NAME));
keyStore.load(keyInput, pKeyPassword.toCharArray());
keyInput.close();
keyManagerFactory
.init(keyStore, pKeyPassword.toCharArray());
/*
* Trustore manager
*/
TrustManagerFactory trustManagerFactory = TrustManagerFactory
.getInstance("SunX509");
KeyStore trustStore = KeyStore.getInstance("JKS");
InputStream trustInput = new FileInputStream(new File(
cc.getWorkingDir() + File.separator
+ GSBConstants.TRUSTORE_NAME));
String pTrustPassword = GSBConstants.TRUSTORE_PASSWORD;
trustStore.load(trustInput, pTrustPassword.toCharArray());
trustInput.close();
trustManagerFactory.init(trustStore);
SSLContext context = SSLContext.getInstance("SSL");
context.init(keyManagerFactory.getKeyManagers(),
trustManagerFactory.getTrustManagers(),
new SecureRandom());
SSLContext.setDefault(context);
SSLSocketFactory sockFact = context.getSocketFactory();
con.setSSLSocketFactory(sockFact);
// Check for errors
int responseCode = con.getResponseCode();
InputStream inputStream;
if (responseCode == HttpURLConnection.HTTP_OK) {
inputStream = con.getInputStream();
} else {
inputStream = con.getErrorStream();
}
OutputStream output = new FileOutputStream("test.zip");
// Process the response
BufferedReader reader;
String line = null;
reader = new BufferedReader(new InputStreamReader(
inputStream));
while ((line = reader.readLine()) != null) {
output.write(line.getBytes());
}
output.close();
inputStream.close();
Any ideas ?
I don't have any exceptions.
I am using the code below to connect to https site. But the result is always a blank page. I have already searched alot. Any help will be appreciated.
public boolean shouldOverrideUrlLoading(WebView view, String url)
{ try
{
InputStream keyStoreStream = getResources().openRawResource(R.raw.jssecacerts);
KeyStore keyStore = null;
keyStore = KeyStore.getInstance("BKS");
keyStore.load(keyStoreStream, "mypwd".toCharArray());
KeyManagerFactory keyManagerFactory = null;
keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, "mypwd".toCharArray());
SSLContext context = SSLContext.getInstance("TLS");
context.init(keyManagerFactory.getKeyManagers(), null, null);
alertbox("before response", url);
URL url1 = new URL(url);
HttpsURLConnection urlConnection = (HttpsURLConnection) url1.openConnection();
urlConnection.setSSLSocketFactory(context.getSocketFactory());
InputStream in = urlConnection.getInputStream();
alertbox("response", convertToString(in));
view.loadData(convertToString(in), "text/html", "utf-8");
}
catch(Exception e)
{
e.printStackTrace();
}
return true;
}
have you tried something as simple as
webview.loadUrl("URL HERE");