Ho 2 app, una è un server Servlet/Tomcat e l'altra è un'app Android.Android: connessione HTTPS (SSL) utilizzando HttpsURLConnection
Desidero utilizzare HttpURLConnection per inviare e ricevere XML tra entrambi.
Codice:
private String sendPostRequest(String requeststring) {
DataInputStream dis = null;
StringBuffer messagebuffer = new StringBuffer();
HttpURLConnection urlConnection = null;
try {
URL url = new URL(this.getServerURL());
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setDoOutput(true);
urlConnection.setRequestMethod("POST");
OutputStream out = new BufferedOutputStream(urlConnection.getOutputStream());
out.write(requeststring.getBytes());
out.flush();
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
dis = new DataInputStream(in);
int ch;
long len = urlConnection.getContentLength();
if (len != -1) {
for (int i = 0; i < len; i++)
if ((ch = dis.read()) != -1) {
messagebuffer.append((char) ch);
}
} else {
while ((ch = dis.read()) != -1)
messagebuffer.append((char) ch);
}
dis.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
urlConnection.disconnect();
}
return messagebuffer.toString();
}
Ora, ho bisogno di utilizzare SSL per inviare le XMLs per la sicurezza.
Per prima cosa, utilizzo Java Keytool per generare il file .keystore.
Keytool -keygen -alias tomcat -keyalg RSA
poi ho messo il codice XML file server.xml di Tomcat per utilizzare SSL
<Connector
port="8443" protocol="HTTP/1.1" SSLEnabled="true"
maxThreads="150" scheme="https" secure="true"
keystoreFile="c:/Documents and Settings/MyUser/.keystore"
keystorePass="password"
clientAuth="false" sslProtocol="TLS"
/>
Poi, lo cambio il HttpURLConnection per HttpsURLConnection
private String sendPostRequest(String requeststring) {
DataInputStream dis = null;
StringBuffer messagebuffer = new StringBuffer();
HttpURLConnection urlConnection = null;
//Conexion por HTTPS
HttpsURLConnection urlHttpsConnection = null;
try {
URL url = new URL(this.getServerURL());
//urlConnection = (HttpURLConnection) url.openConnection();
//Si necesito usar HTTPS
if (url.getProtocol().toLowerCase().equals("https")) {
trustAllHosts();
//Creo la Conexion
urlHttpsConnection = (HttpsURLConnection) url.openConnection();
//Seteo la verificacion para que NO verifique nada!!
urlHttpsConnection.setHostnameVerifier(DO_NOT_VERIFY);
//Asigno a la otra variable para usar simpre la mism
urlConnection = urlHttpsConnection;
} else {
urlConnection = (HttpURLConnection) url.openConnection();
}
//Do the same like up
e aggiungere un trustAllHosts metodo per fidarsi di ogni server (non controllare per qualsiasi certificato)
private static void trustAllHosts() {
X509TrustManager easyTrustManager = new X509TrustManager() {
public void checkClientTrusted(
X509Certificate[] chain,
String authType) throws CertificateException {
// Oh, I am easy!
}
public void checkServerTrusted(
X509Certificate[] chain,
String authType) throws CertificateException {
// Oh, I am easy!
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] {easyTrustManager};
// Install the all-trusting trust manager
try {
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
e.printStackTrace();
}
}
Queste modifiche hanno funzionato molto bene, ma non voglio fidarmi di ogni server. Voglio usare il mio file di archivio chiavi per convalidare la connessione e usare SSL nel modo giusto. Ho letto molto su internet e ho fatto un sacco di test, ma non riesco a capire cosa devo fare e come farlo.
Qualcuno può aiutarmi?
La ringrazio molto
Ci dispiace per il mio povero inglese
------------------------- UPDATE 2011/08/24 ------------------------------------------------ -
Beh, ci sto ancora lavorando. Ho fatto un nuovo metodo per impostare il KeyStore, InputStream, ecc
Il metodo è simile al seguente:
private static void trustIFNetServer() {
try {
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore ks = KeyStore.getInstance("BKS");
InputStream in = context.getResources().openRawResource(R.raw.mykeystore);
String keyPassword = "password";
ks.load(in, keyPassword.toCharArray());
in.close();
tmf.init(ks);
TrustManager[] tms = tmf.getTrustManagers();
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, tms, new java.security.SecureRandom());
} catch (Exception e) {
e.printStackTrace();
}
}
Prima ho avuto un sacco di problemi con la chiave e il certificato, ma ora si sta lavorando (Penso di sì)
Il mio problema adesso è un'eccezione TimeOut. Non so perché viene generato. Penso che sia qualcosa con la scrittura dei dati, ma non posso ancora risolverlo.
Qualche idea?
Si sta utilizzando un certificato firmato da un'autorità di certificazione noto o stai usando un certificato auto-firmato? –