I have a java application that is making an HTTP DELETE to an external REST service. This error gets back to me from the server (running C#):
"Value cannot be null.\r\nParameter name: source\n at System.Linq.Enumerable.Count[TSource](IEnumerable`1 source)\r\n at AppCloud_Framework.Controllers.NotificationItemsController.DeleteNotificationItem(NotificationItem[] notificationItems) in C:\\Users\\jonas\\OneDrive\\VS Projects\\AppCloud Framework\\AppCloud Framework\\Controllers\\NotificationItemsController.cs:line 101\nValue:null"
The thing is, when I setup Postman to make the HTTP request to the same URL, with the same Payload and same HTTP method, the action is successful.
I do not have access to the server to investigate further so I need to find the resolution from the client side. Anyway it appears to be a client side issue.
I've been trying to find the problem myself but haven't succeeded. All I could come up with was to add "application/json" to Accept and Content-Type header properties.
My HTTP client:
public static Response execute(String url, Method method, String body) {
Response response = new Response();
try {
////////////////////////////////////////
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
} };
// Install the all-trusting trust manager
final SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
// Create all-trusting host name verifier
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
// Install the all-trusting host verifier
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
////////////////////////////////////////
URL urlObj = new URL(url);
HttpsURLConnection conn = (HttpsURLConnection) urlObj.openConnection();
conn.setInstanceFollowRedirects(false);
conn.setRequestMethod(method.toString());
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("Accept", "application/json");
//conn.setRequestProperty("Authorization", _authToken);
if (method == Method.POST || method == Method.PUT || method == Method.DELETE) {
conn.setDoOutput(true);
final OutputStream os = conn.getOutputStream();
os.write(body.getBytes());
os.flush();
os.close();
}
int status = conn.getResponseCode();
//log.info("HTTP request status code: "+status);
InputStream is;
if (status>399){
is = conn.getErrorStream();
}else{
is = conn.getInputStream();
}
if (is==null) return null;
BufferedReader rd = new BufferedReader(new InputStreamReader(is,
"UTF-8"));
String line;
while ((line = rd.readLine()) != null) {
response.body += line;
}
rd.close();
response.statusCode = conn.getResponseCode();
conn.disconnect();
} catch (Exception e) {
//log.error(e.getMessage());
e.printStackTrace();
System.out.println("");
response.exception = e.getMessage();
}
return response;
}
I am making a request with this body(disregard the encoding issue, source of that is somewhere else):
[{"hash":"150a17e99f67ce29fcc600c92eee831d","instanceid":"cb440a6f-44ef-4f05-ab41-143153655b6e","text":"{\"C_FirstAndLastName\":\"und\",\"ContactID\":\"1374231\",\"C_Fax\":\"\"}","queueDate":"2016-10-04T03:18:37"},{"hash":"1a94d9b5acff1a27dfe45be4ca5d9138","instanceid":"fdsfdsf-44ef-4f05-ab41-143153655b6e","text":"{\"C_FirstAndLastName\":\"J?â??rgen\",\"ContactID\":\"323093\",\"C_Fax\":\"fsdfsd-B401-4AD3-AEA1-fdsfsdfsd\"}","queueDate":"2016-10-04T03:18:37"},{"hash":"8e592fb16d464bfd0f90f69818944198","instanceid":"fdsfsdf-44ef-4f05-ab41-143153655b6e","text":"{\"C_FirstAndLastName\":\"Claus\",\"ContactID\":\"2495844\",\"C_Fax\":\"fdsfsdgsd-304D-4E91-8586-fsdfsdfsd\"}","queueDate":"2016-10-04T03:18:37"},{"hash":"d6d226255e62690e50abbfa15c4b5462","instanceid":"cb440a6f-44ef-4f05-ab41-143153655b6e","text":"{\"C_FirstAndLastName\":\"Test J??rgen\",\"ContactID\":\"323093\",\"C_Fax\":\"fdsfsdfsd-B401-4AD3-AEA1-fdsfsdfsdf\"}","queueDate":"2016-10-04T03:18:49"}]
All I had to do was to define encoding in the output stream. Not sure if anyone could help me with that as I have just tried many things and some of it worked, but unfortunately nothing was pointing me into this direction.
os.write(body.getBytes("UTF-8"));
Related
I'm trying to get some data by the rest api of Jira. Thiw website is locally in my enterprise and on https. The first time we go on it we are automatically login by SSO. There are certificats too.
I have check all post about this error, try with User-Agent or TrustManager but nothing work :( then I can access to the page by my browser without any problem. It's work on two other computer and I didn't really understand why.
Error I got :
java.io.IOException: Server returned HTTP response code: 403 for URL: https://myjira.xx/rest/api/2/search?jql=project=PARE2+order+by+updated&fields=id,updated,summary,assignee,worklog&startAt=0&maxResults=30
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
And my code is :
public void connectToJira() throws Exception {
String adresse = "https://myjira.xx/";
adresse += "rest/api/2/search?jql=project=NAMEProject+order+by+updated&fields=id,updated,summary,assignee,worklog&startAt=0&maxResults=30";
TrustManager[] trustAllCerts = { new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
} };
try {
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
}
URL url = new URL(adresse);
HttpURLConnection uc = (HttpURLConnection) url.openConnection();
uc.addRequestProperty("User-Agent", "Mozilla/5.0");
uc.setRequestProperty("Authorization", "Basic " + new String(Base64.getEncoder().encode("myUsername:myPassword".getBytes())));
if (401 == uc.getResponseCode()) {
throw new Exception("Code erreur 401");
}
StringBuilder sb = new StringBuilder();
BufferedReader reader = new BufferedReader(new InputStreamReader(uc.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
System.out.println(sb.toString());
}
I try to add certificats from my cacerts but same problem :(
Thanks
This is my Https client
public String sendHttpsRequest(String httpsUrl, HttpMethod method,
String body, Map<String, String> headers) {
String response = "";
int responseCode = 0;
HttpsURLConnection conn = null;
try {
URL url = new URL(httpsUrl);
conn = (HttpsURLConnection) url.openConnection();
conn.setRequestMethod(method.toString());
for (Map.Entry<String, String> entry : headers.entrySet()) {
conn.setRequestProperty(entry.getKey(), entry.getValue());
}
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setHostnameVerifier(new HostnameVerifier() {
#Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, new TrustManager[]{
new javax.net.ssl.X509TrustManager() {
#Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
#Override
public void checkServerTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
#Override
public void checkClientTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
}
}, null);
conn.setSSLSocketFactory(context.getSocketFactory());
String param = body;
DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
wr.writeBytes(param);
wr.flush();
wr.close();
responseCode = conn.getResponseCode();
InputStream in = conn.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line = "";
while ((line = reader.readLine()) != null) {
response += line;
}
reader.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
if(conn != null) {
conn.disconnect();
}
}
return responseCode == 200?response:Integer.toString(responseCode);
}
but for some reason it gives me a "405 Method not allowed" when I try to conncet to https://httpbin.org/get with following parameters.
TreeMap<String, String> map = new TreeMap<>();
map.put("Content-Type", "application/json");
System.out.println(new HttpLiveTest().sendHttpsRequest("https://httpbin.org/get" , HttpMethod.GET, "", map));
I also tried to connect to it through SoapUI with same parameters and it worked there.
I think the certificate that i'm using from Spring might be the problem but I wouldnt know how to solve that issue and why whould it answer with an 405?
Using Wireshark to look at the package didnt work because of TLS
Arnaud said: setDoOutput(true) may force the method to be POST
hes right.
user7236363 wrote:
java.net.ProtocolException: cannot write to a URLConnection if doOutput=false - call setDoOutput(true) is what im getting when i wont set it on true
he is also right.
Big picture:
What you want to do most of the time is a HTTP GET and that passes arguments in on the url - it doesnt requre any bytes to be written after the url so setting the Connection.setDoOutput(true) is not needed at all, hence dont do it when you want to do a GET.
Between the Connection.setRequestProperty(String Key, String Value) and the URL itself you should have everthing you need to make a properly formatted GET request.
I had a very simular problem and the root of it was me setting setDoOutput(true) and not realizing that it had a side effect that i didnt realize (ie setting the request method to post).
I'm trying to issue a post request in the next manner:
I use Apache's HttpClient 3.1
I use encoding "application/x-www-form-urlencoded"
The URL I use starts with https
this is the code I try to run:
public static String httpsPost(String url, String body, String mediaType, String encoding) {
disableCertificateValidation();
HttpClient client = new HttpClient();
StringRequestEntity requestEntity = new StringRequestEntity(body, mediaType, encoding);
PostMethod method = new PostMethod(url);
method.setRequestEntity(requestEntity);
client.executeMethod(method);
}
public static void disableCertificateValidation() {
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] {
new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {}
public void checkServerTrusted(X509Certificate[] certs, String authType) {}
}};
// Ignore differences between given hostname and certificate hostname
HostnameVerifier hv = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) { return true; }
};
// Install the all-trusting trust manager
try {
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(hv);
} catch (Exception e) {}
}
Upon executing executeMethod I catch:
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
I tried to disable certificate validation but it did not help.
If you want to ignore the certificate all together then take a look at the answer here Ignore self-signed ssl cert using Jersey Client
Although this will make your app vulnerable to man-in-the-middle attacks.
You can instead of this try adding the certificate to your java store as a trusted cert. This site may be helpful. http://blog.icodejava.com/tag/get-public-key-of-ssl-certificate-in-java/
Here's another answer showing how to add a cert to your store. Java SSL connect, add server cert to keystore programatically
The key is
KeyStore.Entry newEntry = new KeyStore.TrustedCertificateEntry(someCert);
ks.setEntry("someAlias", newEntry, null);`
I refactored my old code to handle https. Now it works and looks like this:
public static String httpsPost(String url, String body, String mediaType, String encoding) {
SSLContext ctx;
ctx = SSLContext.getInstance("TLS");
ctx.init(new KeyManager[0], new TrustManager[]{new DefaultTrustManager()}, new SecureRandom());
SSLContext.setDefault(ctx);
HttpsURLConnection.setDefaultSSLSocketFactory(ctx.getSocketFactory());
URL serverUrl = new URL(url);
HttpsURLConnection con = (HttpsURLConnection) serverUrl.openConnection();
con.setRequestMethod("POST");
con.setDoOutput(true);
con.connect();
OutputStreamWriter post = new OutputStreamWriter(con.getOutputStream());
post.write(body);
post.flush();
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
String content = "";
while ((inputLine = in.readLine()) != null) {
content += inputLine;
}
post.close();
in.close();
return content;
}
When I invoke my Webservice I am getting error like below, please explain it how I can solve this problem.
Error is:
fault Description : nulldetail : faultCode:Server.Processing
faultString:'javax.net.ssl.SSLHandshakeException : General SSLEngine
problem' faultDetail:'null'
I am using tomcat server in my local.
I'm using 1.6 Java Runtime Environment and I added Webservice SSL into:
jdk1.6>jre>lib>security>cacerts .
but nothing changed. Do I need configure my tomcat server
I solved the problem . You dont need to any configuration your server . Or JRE .
Just put it this code
public String retrieveMngTracking(ArrayList paramList) throws Exception {
//ı added for SSL
HostnameVerifier hv = new HostnameVerifier() {
public boolean verify(String urlHostName, SSLSession session) {
System.out.println("Warning: URL Host: " + urlHostName
+ " vs. " + session.getPeerHost());
return true;
}
};
ParamMap paramMap = FlexUtil.getParamMap(paramList);
URL url = new URL(paramMap.getString("url"));
//Call this function for SSL
trustAllHttpsCertificates();
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setReadTimeout(20000);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-type",
"application/x-www-form-urlencoded");
OutputStream os = conn.getOutputStream();
OutputStreamWriter wr = new OutputStreamWriter(os);
wr.write("pMusteriNo=" + paramMap.getString("pMusteriNo"));
wr.write("&pSifre=" + paramMap.getString("pSifre"));
wr.write("&pSiparisNo=" + paramMap.getString("pSiparisNo"));
wr.write("&pKriter=" + paramMap.getString("pKriter"));
wr.flush();
wr.close();
os.close();
StringBuffer sb = new StringBuffer();
BufferedReader br = new BufferedReader(new InputStreamReader(
conn.getInputStream()));
String response = "";
for (;;) {
String line = br.readLine();
if (line == null)
break;
response += line + "\n";
}
br.close();
conn.disconnect();
return response;
}
public static class miTM implements javax.net.ssl.TrustManager,
javax.net.ssl.X509TrustManager {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public boolean isServerTrusted(
java.security.cert.X509Certificate[] certs) {
return true;
}
public boolean isClientTrusted(
java.security.cert.X509Certificate[] certs) {
return true;
}
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType)
throws java.security.cert.CertificateException {
return;
}
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType)
throws java.security.cert.CertificateException {
return;
}
}
private static void trustAllHttpsCertificates() throws Exception {
// Create a trust manager that does not validate certificate chains:
javax.net.ssl.TrustManager[] trustAllCerts =
new javax.net.ssl.TrustManager[1];
javax.net.ssl.TrustManager tm = new miTM();
trustAllCerts[0] = tm;
javax.net.ssl.SSLContext sc =
javax.net.ssl.SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, null);
javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(
sc.getSocketFactory());
}
Ok everything perfect in my local my local server is tomcat . But When ı want to deploy Weblogic server same error giving . Please explain it why everything work my local but now weblogic server problem.
I want to do a HTTPS post method to send some data from my android app to my website.
I used HttpURLConnection first and it's working fine with my HTTP URL. My production website is on HTTPS and I want to send the same POST using HttpsURLConnection. Can someone help me use the class properly?
I found some source at this link:
KeyStore keyStore = ...;
TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
tmf.init(keyStore);
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
URL url = new URL("https://www.example.com/");
HttpsURLConnection urlConnection = (HttpsURLConnection)
url.openConnection();
urlConnection.setSSLSocketFactory(context.getSocketFactory());
InputStream in = urlConnection.getInputStream();
What should be the value of KeyStore keyStore = ...;?
I tried sending the data using the same HttpURLConnection, but I am seeing some POST data is missed or in error.
I've tried the method from this question. I am pasting my code below
String urlParameters="dateTime=" + URLEncoder.encode(dateTime,"UTF-8")+
"&mobileNum="+URLEncoder.encode(mobileNum,"UTF-8");
URL url = new URL(myurl);
HttpsURLConnection conn;
conn=(HttpsURLConnection)url.openConnection();
// Create the SSL connection
SSLContext sc;
sc = SSLContext.getInstance("TLS");
sc.init(null, null, new java.security.SecureRandom());
conn.setSSLSocketFactory(sc.getSocketFactory());
conn.setConnectTimeout(HTTP_CONNECT_TIME_OUT);
conn.setReadTimeout(HTTP_READ_TIME_OUT);
//set the output to true, indicating you are outputting(uploading) POST data
conn.setDoOutput(true);
//once you set the output to true, you don't really need to set the request method to post, but I'm doing it anyway
conn.setRequestMethod("POST");
conn.setFixedLengthStreamingMode(urlParameters.getBytes().length);
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
PrintWriter out = new PrintWriter(conn.getOutputStream());
out.print(urlParameters);
out.close();
InputStream is = conn.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(is));
String inputLine;
while ((inputLine = in.readLine()) != null) {
response += inputLine;
}
The error I am getting is below:
05-12 19:36:10.758: W/System.err(1123): java.io.FileNotFoundException: https://www.myurl.com/fms/test
05-12 19:36:10.758: W/System.err(1123): at libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:177)
05-12 19:36:10.758: W/System.err(1123): at libcore.net.http.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:270)
05-12 19:36:10.758: W/System.err(1123): at .httpRequest(SMSToDBService.java:490)
05-12 19:36:10.758: W/System.err(1123): at com..access$0(SMSToDBService.java:424)
05-12 19:36:10.758: W/System.err(1123): at com.$ChildThread$1.handleMessage(SMSToDBService.java:182)
05-12 19:36:10.758: W/System.err(1123): at android.os.Handler.dispatchMessage(Handler.java:99)
05-12 19:36:10.758: W/System.err(1123): at android.os.Looper.loop(Looper.java:156)
05-12 19:36:10.758: W/System.err(1123): at com.$ChildThread.run(SMSToDBService.java:303)
You can use the default CAs that are defined in the android device, which is just fine for any public web.
If you have a self-signed certificate, you can either accept all certificates (risky, open to man-in-the-middle attacks) or create your own TrustManagerFactory, which is a bit out of this scope.
Here's some code to use the default CAs for a https POST call:
private InputStream getInputStream(String urlStr, String user, String password) throws IOException
{
URL url = new URL(urlStr);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
// Create the SSL connection
SSLContext sc;
sc = SSLContext.getInstance("TLS");
sc.init(null, null, new java.security.SecureRandom());
conn.setSSLSocketFactory(sc.getSocketFactory());
// Use this if you need SSL authentication
String userpass = user + ":" + password;
String basicAuth = "Basic " + Base64.encodeToString(userpass.getBytes(), Base64.DEFAULT);
conn.setRequestProperty("Authorization", basicAuth);
// set Timeout and method
conn.setReadTimeout(7000);
conn.setConnectTimeout(7000);
conn.setRequestMethod("POST");
conn.setDoInput(true);
// Add any data you wish to post here
conn.connect();
return conn.getInputStream();
}
To read the response:
String result = new String();
InputStream is = getInputStream(urlStr, user, password);
BufferedReader in = new BufferedReader(new InputStreamReader(is));
String inputLine;
while ((inputLine = in.readLine()) != null) {
result += inputLine;
}
You can take a look at this question I asked a few days ago:
Change HTTP post request to HTTPS post request:
I have supplied there a solution that worked for me, that basically accepts any self-signed certificate. As been said here this solution is not recommended as it's not secure and open to a man-in-the-middle attacks.
Here is the code:
EasySSLSocketFactory:
public class EasySSLSocketFactory implements SocketFactory, LayeredSocketFactory {
private SSLContext sslcontext = null;
private static SSLContext createEasySSLContext() throws IOException {
try {
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, new TrustManager[] { new EasyX509TrustManager(null) }, null);
return context;
} catch (Exception e) {
throw new IOException(e.getMessage());
}
}
private SSLContext getSSLContext() throws IOException {
if (this.sslcontext == null) {
this.sslcontext = createEasySSLContext();
}
return this.sslcontext;
}
/**
* #see org.apache.http.conn.scheme.SocketFactory#connectSocket(java.net.Socket, java.lang.String, int,
* java.net.InetAddress, int, org.apache.http.params.HttpParams)
*/
public Socket connectSocket(Socket sock, String host, int port, InetAddress localAddress, int localPort,
HttpParams params) throws IOException, UnknownHostException, ConnectTimeoutException {
int connTimeout = HttpConnectionParams.getConnectionTimeout(params);
int soTimeout = HttpConnectionParams.getSoTimeout(params);
InetSocketAddress remoteAddress = new InetSocketAddress(host, port);
SSLSocket sslsock = (SSLSocket) ((sock != null) ? sock : createSocket());
if ((localAddress != null) || (localPort > 0)) {
// we need to bind explicitly
if (localPort < 0) {
localPort = 0; // indicates "any"
}
InetSocketAddress isa = new InetSocketAddress(localAddress, localPort);
sslsock.bind(isa);
}
sslsock.connect(remoteAddress, connTimeout);
sslsock.setSoTimeout(soTimeout);
return sslsock;
}
/**
* #see org.apache.http.conn.scheme.SocketFactory#createSocket()
*/
public Socket createSocket() throws IOException {
return getSSLContext().getSocketFactory().createSocket();
}
/**
* #see org.apache.http.conn.scheme.SocketFactory#isSecure(java.net.Socket)
*/
public boolean isSecure(Socket socket) throws IllegalArgumentException {
return true;
}
/**
* #see org.apache.http.conn.scheme.LayeredSocketFactory#createSocket(java.net.Socket, java.lang.String, int,
* boolean)
*/
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException,
UnknownHostException {
return getSSLContext().getSocketFactory().createSocket(socket, host, port, autoClose);
}
// -------------------------------------------------------------------
// javadoc in org.apache.http.conn.scheme.SocketFactory says :
// Both Object.equals() and Object.hashCode() must be overridden
// for the correct operation of some connection managers
// -------------------------------------------------------------------
public boolean equals(Object obj) {
return ((obj != null) && obj.getClass().equals(EasySSLSocketFactory.class));
}
public int hashCode() {
return EasySSLSocketFactory.class.hashCode();
}
}
EasyX509TrustManager:
public class EasyX509TrustManager implements X509TrustManager {
private X509TrustManager standardTrustManager = null;
/**
* Constructor for EasyX509TrustManager.
*/
public EasyX509TrustManager(KeyStore keystore) throws NoSuchAlgorithmException, KeyStoreException {
super();
TrustManagerFactory factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
factory.init(keystore);
TrustManager[] trustmanagers = factory.getTrustManagers();
if (trustmanagers.length == 0) {
throw new NoSuchAlgorithmException("no trust manager found");
}
this.standardTrustManager = (X509TrustManager) trustmanagers[0];
}
/**
* #see javax.net.ssl.X509TrustManager#checkClientTrusted(X509Certificate[],String authType)
*/
public void checkClientTrusted(X509Certificate[] certificates, String authType) throws CertificateException {
standardTrustManager.checkClientTrusted(certificates, authType);
}
/**
* #see javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[],String authType)
*/
public void checkServerTrusted(X509Certificate[] certificates, String authType) throws CertificateException {
if ((certificates != null) && (certificates.length == 1)) {
certificates[0].checkValidity();
} else {
standardTrustManager.checkServerTrusted(certificates, authType);
}
}
/**
* #see javax.net.ssl.X509TrustManager#getAcceptedIssuers()
*/
public X509Certificate[] getAcceptedIssuers() {
return this.standardTrustManager.getAcceptedIssuers();
}
}
And I added this method: getNewHttpClient()
public static HttpClient getNewHttpClient() {
try {
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null, null);
SSLSocketFactory sf = new MySSLSocketFactory(trustStore);
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
registry.register(new Scheme("https", sf, 443));
ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);
return new DefaultHttpClient(ccm, params);
} catch (Exception e) {
return new DefaultHttpClient();
}
}
Finally for every place in my code that I had:
DefaultHttpClient client = new DefaultHttpClient();
I replace it with:
HttpClient client = getNewHttpClient();
Here's an Android HttpsUrlConnection POST solution complete with certificate pinning, timeouts server side code and configurations.
The variable params should be in the form username=demo&password=abc123&.
#Override
public String sendHttpRequest(String params) {
String result = "";
try {
URL url = new URL(AUTHENTICATION_SERVER_ADDRESS);
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setSSLSocketFactory(KeyPinStore.getInstance().getContext().getSocketFactory()); // Tell the URLConnection to use a SocketFactory from our SSLContext
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setConnectTimeout(10000);
connection.setReadTimeout(10000);
PrintWriter out = new PrintWriter(connection.getOutputStream());
out.println(params);
out.close();
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()), 8192);
String inputLine;
while ((inputLine = in.readLine()) != null) {
result = result.concat(inputLine);
}
in.close();
//} catch (IOException e) {
} catch (IOException | KeyStoreException | CertificateException | KeyManagementException | NoSuchAlgorithmException e) {
result = e.toString();
e.printStackTrace();
}
return result;
}