Ändern von HTTP-post-request HTTPS post-Anforderung:
Habe ich diese Methode:
public static String getReportMetadata (String reportId, String sessionId, String url) throws Exception{
Map<String, Object> jsonValues = new HashMap<String, Object>();
jsonValues.put("reportID", reportId);
jsonValues.put("sessionID", sessionId);
JSONObject json = new JSONObject(jsonValues);
DefaultHttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(url + GET_REPORT_METADATA_ACTION);
AbstractHttpEntity entity = new ByteArrayEntity(json.toString().getBytes("UTF8"));
entity.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
post.setEntity(entity);
HttpResponse response = client.execute(post);
return getContent(response);
}
führen, dass ein HTTP
Post-Anforderung, die der-natürlich Lauf ich mit AsyncTask
um Daten aus der server.
Meine Frage:
könnte jemand mir bitte erklären, in einer einfachen Weise, was sind die Schritte, die ich ausführen muss, um dies zu ändern, Verbindungstyp, um eine sichere Verbindung(ein.k.ein mit HTTPS
).
Nur aus android-Sicht (d.h. die client-Anwendung).
UPDATE:
Wie vorgeschlagen, habe ich versucht zu ändern, nur den link und fügen Sie https anstelle von http, aber es nicht wieder eine Antwort. Wie ich verstehe, dass ich brauchen, um Holen Sie sich und speichern Sie ein self-sign Zertifikat, um die Verbindung zu server side
UPDATE2:
Die Lösung, die für mich funktioniert:
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();
}
}
Und ich fügte hinzu, diese Methode: 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();
}
}
Schließlich für jeden Platz in meinem code, das ich hatte:
DefaultHttpClient client = new DefaultHttpClient();
Ich es ersetzen mit:
HttpClient client = getNewHttpClient();
Ich bin jetzt in der Lage, um den Empfang der Daten von der server-Seite, die Letzte Frage ist: ist das, was ich getan habe ist sicher? oder es nimmt jeder sich selbst-signiertes Zertifikat? wenn dies der Fall ist, was getan werden sollte, um es zu ändern?
Jede mögliche Hilfe würde geschätzt.
Nach der HTTPClient SSL Guide, wirklich das einzige, was Sie tun müssen ist, setzen Sie "https://" in der URL-Zeichenfolge. Dadurch erhalten Sie eine HTTPS-Verbindung mit einem browser-gleichwertige Ebene der Authentifizierung (d.h. eine von mehreren hundert CA ' s signieren können das server-Zertifikat). Die
SchemeRegistry
und SSLSocketFactory
nur ins Spiel kommen wenn Sie möchten, passen Sie die SSL-Handhabung, in der Regel implementieren von SSL-pinning (das ist, verwenden Sie eine stärkere Authentizität Einschränkung). Check-out Moxie ' s github für eine gute (LGPL lizenziert) Android ssl-pinner.Ich habe versucht zu ändern, nur den link und fügen Sie https anstelle von http, aber es doens ' T Rückkehr eine Antwort. Wie ich verstehe, dass ich brauchen, um Holen Sie sich und speichern Sie ein self-sign Zertifikat, um die Verbindung zu der server-Seite.
Ach, du hast nie erwähnt, dass der Endpunkt ausgeführt wird, ein selbst signiertes Zertifikat. Yep, müssen Sie erstellen eine benutzerdefinierte
SSLSocketFactory
- Instanz mithilfe der SSLSocketFactory(KeyStore trustStore)
Konstruktor. Den keystore, die Sie übergeben müssen Ihre server-Zertifikat.Ich bin neu, um all dies sichere Verbindung Zeug, also ich hatte keine Ahnung, dass es einen Unterschied macht. würden Sie mir zu erarbeiten, ein wenig mehr zu diesem Thema oder stellen Sie eine code-snippet? das wäre wirklich hilfreich.
InformationsquelleAutor Emil Adz | 2013-05-05
Du musst angemeldet sein, um einen Kommentar abzugeben.
Aus der Apache-HttpClient SSL guide:
So dass Sie sich einfach ändern sollten, http://XXXX zu https://XXXX
EDIT: ich habe gerade gesehen @Barend 's Antwort, die mehr vollständige
Wenn der server ein selbstsigniertes Zertifikat ausgibt, müssen Sie auf dem HttpClient, es zu akzeptieren. Wenn Sie dies tun möchten Sie können schauen Sie hier, stackoverflow.com/questions/1217141/...
InformationsquelleAutor user2340612
Zuerst müssen Sie erstellen SchemeRegistry-Objekt und registrieren Sie die neue Regelung SSLSocketFactory:
Dann können Sie Ihre SingleClientConnManager mit SchemeRegistry Objekt:
Und schließlich erstellen Sie Ihre DefaultHttpClient mit SingleClientConnManager:
Ja, sollten Sie diese Schritte durchführen, bevor Sie jede https-Zugriff.
SchemeRegistry
ist nur ein container für alleScheme
Objekte, die beschreibt, HTTPS-Verbindung Parameter, so dass Sie können verwenden Sie eine Instanz vonSchemeRegisty
Objekt für alle Ihre Anrufe. Aber Sie müssen neueSingleClientConnManager
für jeden Anruf, denn es kann nur eine einzige Verbindung zu einer Zeit. Ich denke, dass die Speicherung von SSL-Zertifikaten wird durch Android selbst, so dass Sie nicht brauchen, um über sorgen es.InformationsquelleAutor nemezis