I am facing a problem to call https from Android. Can any one please help with steps to connect to the https server.
I tried to connect to google with https and its working fine but when I try to connect to my local server, I am facing problems.
want to connect a RESTful web service with https
want to connect a SOAP based web service developed using JAX-WS with https.
Code to connect with RESTFul
HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
DefaultHttpClient client = new DefaultHttpClient();
SchemeRegistry registry = new SchemeRegistry();
SSLSocketFactory socketFactory = SSLSocketFactory.getSocketFactory();
socketFactory.setHostnameVerifier((X509HostnameVerifier) hostnameVerifier);
registry.register(new Scheme("https", socketFactory, 443));
SingleClientConnManager mgr = new SingleClientConnManager(client.getParams(), registry);
DefaultHttpClient httpClient = new DefaultHttpClient(mgr, client.getParams());
// Set verifier
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
// Example send http request
//final String url = "https://encrypted.google.com/";
final String url = "https://ipaddress:8181/RESTTest/cars";
HttpPost httpPost = new HttpPost(url);
try{
HttpResponse response = httpClient.execute(httpPost);
System.out.println(response);
}catch(Exception e){
e.printStackTrace();
}
its working fine for google but not working for my server and it's giving
javax.net.ssl.SSLException: Not trusted server certificate
Code for connect with SOAP:
public String getString(final String methodName, Map<String, Object> params) throws Exception {
HttpTransportSE httpsTransportSE = new HttpTransportSE("https://ipaddress:8181/BankingWS/banking?wsdl");
try {
SoapObject request = new SoapObject("https://test/",
methodName);
if(params != null && params.size() > 0){
Set<String> keys = params.keySet();
Iterator<String> iterator = keys.iterator();
while(iterator.hasNext()){
String key = iterator.next();
request.addProperty(key, params.get(key));
key = null;
}
}
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
SoapEnvelope.VER11);
envelope.setOutputSoapObject(request);
TrustManagerManipulator.allowAllSSL();
httpsTransportSE.call(methodName, envelope);
SoapPrimitive sp = (SoapPrimitive) envelope.getResponse();
return sp.toString();
} catch (Exception exception) {
System.out.println(exception.toString());
throw exception;
}
}
In above code using the TrustManagerManipulator from following link:
http://abhinavasblog.blogspot.com/2011/07/allow-untrusted-certificate-for-https.html
This is also not working and when I check the response code it's giving
SoapFault - faultcode: 'S:Client' faultstring: 'Cannot find dispatch method for {test.WSEndPointPort}authenticate' faultactor: 'null' detail: null
Please help to fix this problem, as I am not able to call https from Android by any way :(
Thank you very much for your time and efforts.
Thank you,
Ishan
You need to create a X509TrustManager which bypass all the security check. You can find an example in this similar questions:
Make a connection to a HTTPS server from Java and ignore the validity of the security certificate
or
How to ignore SSL certificate errors in Apache HttpClient 4.0
Related
I am trying to do HTTP post request in a REST backend. The URL for the backend is using SSL therefore I have also added the necessary code to handle that. But I got the following response:
Cannot POST /api
Here is my code:
protected String doInBackground(String... args) {
try {
HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
DefaultHttpClient client = new DefaultHttpClient();
SchemeRegistry registry = new SchemeRegistry();
SSLSocketFactory socketFactory = SSLSocketFactory.getSocketFactory();
socketFactory.setHostnameVerifier((X509HostnameVerifier) hostnameVerifier);
registry.register(new Scheme("https", socketFactory, 443));
SingleClientConnManager mgr = new SingleClientConnManager(client.getParams(), registry);
DefaultHttpClient httpClient = new DefaultHttpClient(mgr, client.getParams());
HttpPost post = new HttpPost("https://test-api.smart-trial.dk/api");
List <NameValuePair> nvps = new ArrayList <NameValuePair>(2);
nvps.add(new BasicNameValuePair("path[pathwayId]","5566e151817a62021b1ea809"));
nvps.add(new BasicNameValuePair("formData[firstname]","Name"));
nvps.add(new BasicNameValuePair("formData[lastname]","XXX"));
nvps.add(new BasicNameValuePair("formData[email]","example#mail.com"));
post.addHeader("Referer" ,"https://myurl.com/api");
post.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
//DefaultHttpClient httpClient = new DefaultHttpClient();
HttpResponse response = httpClient.execute(post);
HttpEntity entity = response.getEntity();
if (entity != null) {
// get the response content as a string
String stringResponse = EntityUtils.toString(entity);
Log.d("Response", stringResponse);
}
Anything wrong in the code ? Or at least why do I get that response.
EDIT
I also have some rules for the paramaters.
"The post should be done with x-www-form-urlencoded body parameters"
I think more or less I over that by using post.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8)); which x-www-form-urlencoded.
Parameters:
pathwayId (should be located in path)
firstname (should be located in formData)
lastname (should be located in formData)
email (should be located in formData)
Referer (Should be located in Header)
Sounds like your server is not configured to allow POST requests to that URL. But you need a way to verify that.
If you don't already have a REST testing plugin for your browser, find a plugin that will allow you to enter POST request data, download it and install it.
Then duplicate the POST data in the browser plugin, submit the request and view the response from the server.
At least this should help you figure out if the problem is in the app or in the server.
Good day, may ask for advice.
My code is worked properly, but one day for no apparent reason and without changes to the code on the server stopped working, displaying this error
I have checked the decisions referred to by links, but none of them gave the desired result.
Perhaps there was something in the SSL protocol?
Safely fixing: javax.net.ssl.SSLPeerUnverifiedException: No peer certificate
javax.net.ssl.sslpeerunverifiedexception no peer certificate
Android ssl: javax.net.ssl.SSLPeerUnverifiedException: No peer certificate
Trusting all certificates using HttpClient over HTTPS
class RequestTask extends AsyncTask<String, String, String> {
#Override
protected String doInBackground(String... params) {
try {
HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
DefaultHttpClient client = new DefaultHttpClient();
SchemeRegistry registry = new SchemeRegistry();
SSLSocketFactory socketFactory = SSLSocketFactory
.getSocketFactory();
socketFactory
.setHostnameVerifier((X509HostnameVerifier) hostnameVerifier);
registry.register(new Scheme("https", socketFactory, 443));
SingleClientConnManager mgr = new SingleClientConnManager(
client.getParams(), registry);
DefaultHttpClient httpClient = new DefaultHttpClient(mgr,
client.getParams());
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
ResponseHandler<String> res = new BasicResponseHandler();
HttpPost postMethod = new HttpPost("https://api.equalibra.net/banners.json");
nameValuePairs.add(new BasicNameValuePair("lang", "rus"));
postMethod.setEntity(new UrlEncodedFormEntity(nameValuePairs,
HTTP.UTF_8));
String response = "";
try {
response = httpClient.execute(postMethod, res);
} catch (Exception e) {
Log.d("my", e.toString());
}
JSONURL(response);
} catch (Exception e) {
}
return null;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
}
The server requires use of SNI (server name indication). Connections not using SNI will simply fail instead of the usual case where they get a default certificate. Since this is a setting on the server side it might have changed recently so that it broke your code.
While SNI is available in newer versions of the Apache HTTP client library it is not available in the version shipped with the Android SDK, which you probably use.
Indeed, the problem was that my Android SDK does not support SNI .
It helped me:
I am trying to insert a record into MySQL by posting data to a PHP server from an Android app. I have added the INTERNET permission to AndroidManifest.xml
I get javax.net.ssl.SSLPeerUnverifiedException: No peer certificate
Android code
private void senddata(ArrayList<NameValuePair> data)
{
try
{
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("https://10.0.2.2/insert222.php");
httppost.setEntity(new UrlEncodedFormEntity(data));
HttpResponse response = httpclient.execute(httppost);
}
catch (Exception e) {
// TODO: handle exception
Log.e("log_tag", "Error: "+e.toString());
}
}
Can anyone help?
Warning: Do not implement this in production code you are ever going to use on a network you do not entirely trust. Especially anything going over the public internet. This link gives more correct answer. Here is an implementation using SSL.
Your problem is you are using DefaultHttpClient for https(secure url).
Create a custom DefaultHttpClient
public static HttpClient createHttpClient()
{
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.DEFAULT_CONTENT_CHARSET);
HttpProtocolParams.setUseExpectContinue(params, true);
SchemeRegistry schReg = new SchemeRegistry();
schReg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
schReg.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
ClientConnectionManager conMgr = new ThreadSafeClientConnManager(params, schReg);
return new DefaultHttpClient(conMgr, params);
}
Than change your code as follows:
HttpClient httpclient = createHttpClient();
HttpPost httppost = new HttpPost("https://10.0.2.2/insert222.php");
httppost.setEntity(new UrlEncodedFormEntity(data));
HttpResponse response = httpclient.execute(httppost);
Have a look at here if you have problems
It should work.
I had this issue with an IIS 8 server. In the https binding, I had to uncheck the checkbox labeled "Require Server Name Indication." Once I unchecked it, I quit getting the error.
I have to say all trusted certificates (trusted by authorized centres such as COMODO, Symantec, etc.) have to be work in any case. If your app recieves such javax.net.ssl.SSLPeerUnverifiedException: No peer certificate using bought certificate you give something wrong on server side.
To test use openssl s_client -connect example.com:443 command to get inner information about certificate your app recieve.
In may case my nginx-server sent wrong certificate in some cases.
I'm developing android application, which connecting to server via https connection.
I've created my_store.bks file with trusted sertificate and using following code to connect to server :
DefaultHttpClient httpclient = new DefaultHttpClient();
KeyStore trustStore = KeyStore.getInstance("BKS");
InputStream in = context.getResources().openRawResource(R.raw.my_store);
try{
trustStore.load(in,pass.toCharArray());
}
catch(Exception e){
Log.v("MyLog", "errror reading sert: " + e.toString());
}
finally{
in.close();
}
SSLSocketFactory socketFactory = new SSLSocketFactory(trustStore);
Scheme sch = new Scheme("https", socketFactory, 443);
httpclient.getConnectionManager().getSchemeRegistry().register(sch);
HttpPost poster = new HttpPost(serverAdress);
UrlEncodedFormEntity ent = new UrlEncodedFormEntity(formparams,"UTF-8");
poster.setEntity(ent);
HttpResponse responsePost = httpclient.execute(poster);
but when I'm executing this code, I've got next error:
javax.net.ssl.SSLPeerUnverifiedException: No peer certificate No peer certificate
here is some similar problem
No peer cert. Not sure which route to take but i don't want ignore SSL certificates.
Does anyone know what it may be? May it be some server error? (server is developing, so may have errors, but in browser it works fine with sert).
I know this question has been asked before but none of the answers I have found are helping me. I am trying to connect to a simple login service over SSL with Basic Http Auth. The service is hosted at https://localhost:8443/login. When I hit the service from a browser (on windows, OSX, and Android) it works fine, I put in my username and password and I am authenticated properly. However, when I try to do this through code on my Xoom I get a ClientProtocolException that says "the server failed to respond with a valid HTTP response". Can anyone give me a push in the right direction? Here is my code
String result = null;
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.DEFAULT_CONTENT_CHARSET);
HttpProtocolParams.setUseExpectContinue(params, true);
SchemeRegistry schReg = new SchemeRegistry();
schReg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
schReg.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
ClientConnectionManager conMgr = new ThreadSafeClientConnManager(params, schReg);
DefaultHttpClient client = new DefaultHttpClient(conMgr, params);
HttpGet get = new HttpGet(preferences.getString(getString(R.string.Security_Login_URL),
"https://localhost:80/login"));
String credentials = Base64.encodeToString((username + ":" + password).getBytes(), Base64.URL_SAFE);
if(credentials!=null){
get.addHeader("Authorization","Basic "+credentials);
ResponseHandler responseHandler=new BasicResponseHandler();
try {
result = client.execute(get, responseHandler);
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Two common problems could cause this:
You should not do the BASIC authentication yourself. The Apache HttpClient has all the functionalities already included to do the BASIC authentication. Look either Basic Authentication or Preemptive BASIC authentication
Does your android device trusts the certificate from the server? When your browser trusts the cert, it doesn't mean that your device is also trusting it. Android has a very limited list of trusted certification authorities. You could check this from your device, when you visit the site on your Android built-in browser. If no warning message appears, everything should be OK. For further information about trusting additional certificates from an android device, you can look at my blog article.
Enjoy