קריאה ל-Web Service באמצעות Android עם SSL

שיווקי

New member
קריאה ל-Web Service באמצעות Android עם SSL

יש לי אתר SSL.
האתר לא עובר את האבטחה של ה-SSL (ה-token לא מתאים), אך ניתן לראותו בדפדפנים ללא בעיה.

כשאני מנסה לקרוא ל-WebService באתר באמצעות ה-Android אני מקבל הודעת שגיאה.
java.security.cert.certpathvalidatorexception trust anchor for certification path not found

על class מסוג:
javax.net.ssl.SSLHandshakeException

אני לא מבין למה ההקשחה ל-SSL דווקא במערכת android (האם זה קשור לרישום מול google aps?)
כן, האם אפשר בכל זאת "לעקוף" את הבעיה הנ"ל.

תודה.

מצו"ב קוד (השורה הרלוונטית מתחילה ב-4 כוכביות // **** java.security.cert )

package mypackage;

import java.security.cert.CertPathValidatorException;
import java.security.cert.CertificateFactory;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;

import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;

import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.auth.NTCredentials;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.DefaultHttpClient;

import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapPrimitive;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import il.prodware.axlogin.MySSLSocketFactory;

@SuppressLint("ShowToast")
public class MainActivity extends Activity {
private final String NAMESPACE = "";
private final String URL = "https://mymobile.com:8082/Service.svc?wsdl";
private final String SOAP_ACTION = "HelloWorld";
private final String METHOD_NAME = "HelloWorld";


//HttpClient httpclient;
Button b;
EditText edtUserName;
EditText edtPassword;
NTCredentials creds;
HttpClient client;
String s;
String numVal;
TextView txtTest;

HostnameVerifier hostnameVerifier;
SSLSocketFactory socketFactory;
SchemeRegistry registry;
CertificateFactory cf;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
b = (Button)findViewById(R.id.btnSignIn);
Toast.makeText(getApplicationContext(), "start", 1);
numVal = "";
b.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
AsyncCallWS task = new AsyncCallWS();
task.execute();
}
});
}

public void getResult() {
//Create request
SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
SoapEnvelope.VER11);
envelope.dotNet = true;
envelope.setOutputSoapObject(request);
HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);

try {
//Invole web service
//envelope.
hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
socketFactory = org.apache.http.conn.ssl.SSLSocketFactory.getSocketFactory();
registry = new SchemeRegistry();
registry.register(new Scheme("https", socketFactory, 443));
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
androidHttpTransport.call(SOAP_ACTION, envelope); // **** her is the exception
// **** java.security.cert.certpathvalidatorexception trust anchor for certification path not found
// **** class javax.net.ssl.SSLHandshakeException
//Get the response
SoapPrimitive response = (SoapPrimitive) envelope.getResponse();
//Assign it to fahren static variable

} catch (Exception e) {
e.printStackTrace();
}
}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

private class AsyncCallWS extends AsyncTask<String, Void, Void> {
@Override
protected Void doInBackground(String... params) {
// Log.i(TAG, "doInBackground");
getResult();
return null;
}

@Override
protected void onPostExecute(Void result) {
// Log.i(TAG, "onPostExecute");
txtTest.setText("end:" + numVal);
}

@Override
protected void onPreExecute() {
Log.i(TAG, "onPreExecute");
txtTest.setText("bbb...");
}

@Override
protected void onProgressUpdate(Void... values) {
Log.i(TAG, "onProgressUpdate");
}

}

}
 

eladts

New member
מה יש פה להסביר?

אתה בעצמך כתבת שאין certifacte תקין לאתר וזה בדיוק מה שאומרת הודעת השגיאה שאתה מקבל. ככה בדיוק אמור לעבוד SSL.
 

BravoMan

Active member
אם אתה רוצה לעבוד עם סרטיפיקטים לא תקינים

(לא ברור מה הטעם בזה, הרי אתה מחפש אבטחה?) או לעבוד עם סרטיפיקט "חתום עצמית" (self signed) מה שהגיוני בשלב הפיתוח, תצטרך להתאמץ קצת ולעשות Subclass ל-DefaultHttpClient או ליצור TrustManager משלך, ושם להתעלם משגיאות שאתה רוצה להתעלם מהן, או לבדוק סרטיפיקט מול הרשות שאתה רוצה לבדוק (כולל עצמך).

קרא כאן למשל:
http://developer.android.com/training/articles/security-ssl.html#UnknownCa
 

שיווקי

New member
הבנתי, תודה.

שמתי לב ש-SSL לא נכון דיי בעייתי ב-android (אלא, אם עוקפים בדרך לא דרך בקוד באנדרוייד).
זה מה שאני יכול לבדוק כרגע (פוליטיקה ארגונית. דווקא ל-https יש forwards תקין באתר, ול-http לא).

אני מבין שאפשר להתגבר על העניין באמצעות הכלי keytool ועוד כמה פעולות ...

הדוגמה שנתתי היא ל-webservice, ואני מעוניין בפיתרון ל-webservice ולא למשהו אחר.

תודה.
 
למעלה