Connexion Https Android
14 réponses
je fais une supposition, mais si vous voulez qu'une vraie poignée de main se produise, vous devez en informer android de votre certificat. Si vous voulez simplement accepter quoi qu'il arrive, utilisez ce pseudo-code pour obtenir ce dont vous avez besoin avec le Client HTTP Apache:
SchemeRegistry schemeRegistry = new SchemeRegistry ();
schemeRegistry.register (new Scheme ("http",
PlainSocketFactory.getSocketFactory (), 80));
schemeRegistry.register (new Scheme ("https",
new CustomSSLSocketFactory (), 443));
ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager (
params, schemeRegistry);
return new DefaultHttpClient (cm, params);
CustomSSLSocketFactory:
public class CustomSSLSocketFactory extends org.apache.http.conn.ssl.SSLSocketFactory
{
private SSLSocketFactory FACTORY = HttpsURLConnection.getDefaultSSLSocketFactory ();
public CustomSSLSocketFactory ()
{
super(null);
try
{
SSLContext context = SSLContext.getInstance ("TLS");
TrustManager[] tm = new TrustManager[] { new FullX509TrustManager () };
context.init (null, tm, new SecureRandom ());
FACTORY = context.getSocketFactory ();
}
catch (Exception e)
{
e.printStackTrace();
}
}
public Socket createSocket() throws IOException
{
return FACTORY.createSocket();
}
// TODO: add other methods like createSocket() and getDefaultCipherSuites().
// Hint: they all just make a call to member FACTORY
}
FullX509TrustManager est une classe qui implémente javax.net.ssl.X509TrustManager, pourtant aucune des méthodes n'effectue réellement un travail, obtenir un échantillon ici .
Bonne Chance!
C'est ce que je fais. Il ne vérifie plus le certificat.
// always verify the host - dont check for certificate
final static HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
/**
* Trust every server - dont check for any certificate
*/
private static void trustAllHosts() {
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[] {};
}
public void checkClientTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
} };
// 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();
}
}
et
HttpURLConnection http = null;
if (url.getProtocol().toLowerCase().equals("https")) {
trustAllHosts();
HttpsURLConnection https = (HttpsURLConnection) url.openConnection();
https.setHostnameVerifier(DO_NOT_VERIFY);
http = https;
} else {
http = (HttpURLConnection) url.openConnection();
}
en essayant de répondre à cette question, j'ai trouvé un meilleur tutoriel. Avec elle, vous n'avez pas à compromettre la vérification du certificat.
http://blog.crazybob.org/2010/02/android-trusting-ssl-certificates.html
*je n'ai pas écrit cela, mais merci à Bob Lee pour le travail
vous pouvez également regarder mon article de blog, très similaire à crazybobs.
cette solution ne compromet pas non plus la vérification des certificats et explique comment ajouter les certs de confiance dans votre propre keystore.
http://blog.antoine.li/index.php/2010/10/android-trusting-ssl-certificates /
http://madurangasblogs.blogspot.in/2013/08/avoiding-javaxnetsslsslpeerunverifiedex.html
Avec La Permission De Maduranga
lors du développement d'une application qui utilise https, votre serveur de test n'a pas de certificat SSL valide. Ou parfois le site web utilise un certificat auto-signé ou le site web utilise un certificat SSL gratuit. Donc, si vous essayez de vous connecter au serveur en utilisant Apache HttpClient
, vous obtiendrez exception disant que le "pair non authentifié". Si elle n'est pas une bonne pratique de faire confiance à tous les certificats dans un logiciel de production, vous pouvez avoir à le faire selon la situation.
Cette solution résout l'exception causée par "peer not authenticated".
Mais avant d'aller à la solution, je dois vous avertir que ce n'est pas une bonne idée pour une application de production. Ce sera atteinte à l'objet de l'aide d'un certificat de sécurité. Donc à moins que tu aies une bonne raison ou si vous êtes sûr que cela ne cause aucun problème, n'utilisez pas cette solution.
Normalement, vous créez un HttpClient
comme ceci.
HttpClient httpclient = new DefaultHttpClient();
mais vous devez changer la façon dont vous créez le HttpClient.
vous devez d'abord créer une classe prolongeant org.apache.http.conn.ssl.SSLSocketFactory
.
import org.apache.http.conn.ssl.SSLSocketFactory;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
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;
public class MySSLSocketFactory extends SSLSocketFactory {
SSLContext sslContext = SSLContext.getInstance("TLS");
public MySSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
super(truststore);
TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
sslContext.init(null, new TrustManager[] { tm }, null);
}
@Override
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
}
@Override
public Socket createSocket() throws IOException {
return sslContext.getSocketFactory().createSocket();
}
}
alors créer une méthode comme celle-ci.
public 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();
}
}
puis vous peut créer le HttpClient
.
HttpClient httpclient = getNewHttpClient();
Si vous essayez d'envoyer une requête post vers une page de connexion le reste du code sera comme ceci.
private URI url = new URI("url of the action of the form");
HttpPost httppost = new HttpPost(url);
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("username", "user"));
nameValuePairs.add(new BasicNameValuePair("password", "password"));
try {
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
InputStream is = entity.getContent();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
vous obtenez la page html à L'entrée. Ensuite, vous pouvez faire ce que vous voulez avec la page html retournée.
mais ici vous allez faire face à un problème. Si vous voulez gérer une session en utilisant des cookies, vous ne pourrez pas le faire avec ceci méthode. Si vous souhaitez obtenir les cookies, vous devrez le faire via un navigateur. Alors seulement vous recevrez des cookies.
si vous utilisez un certificat StartSSL ou Thawte, il échouera pour Froyo et les versions plus anciennes. Vous pouvez utiliser une nouvelle version du dépôt CAcert au lieu de faire confiance à chaque certificat.
aucun de ceux-ci n'a fonctionné pour moi (aggravé par le bug de dégel ainsi). Finalement je l'ai fait réparer avec acceptation SSL auto-signée sur Android et custom SSL handling stopped working on Android 2.2 FroYo
toutes ces réponses n'ont pas fonctionné pour moi donc voici code qui font confiance à tous les certificats.
import java.io.IOException;
import java.net.Socket;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
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 org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.scheme.PlainSocketFactory;
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.conn.ssl.X509HostnameVerifier;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
public class HttpsClientBuilder {
public static DefaultHttpClient getBelieverHttpsClient() {
DefaultHttpClient client = null;
SchemeRegistry Current_Scheme = new SchemeRegistry();
Current_Scheme.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
try {
Current_Scheme.register(new Scheme("https", new Naive_SSLSocketFactory(), 8443));
} catch (KeyManagementException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnrecoverableKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (KeyStoreException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
HttpParams Current_Params = new BasicHttpParams();
int timeoutConnection = 8000;
HttpConnectionParams.setConnectionTimeout(Current_Params, timeoutConnection);
int timeoutSocket = 10000;
HttpConnectionParams.setSoTimeout(Current_Params, timeoutSocket);
ThreadSafeClientConnManager Current_Manager = new ThreadSafeClientConnManager(Current_Params, Current_Scheme);
client = new DefaultHttpClient(Current_Manager, Current_Params);
//HttpPost httpPost = new HttpPost(url);
//client.execute(httpPost);
return client;
}
public static class Naive_SSLSocketFactory extends SSLSocketFactory
{
protected SSLContext Cur_SSL_Context = SSLContext.getInstance("TLS");
public Naive_SSLSocketFactory ()
throws NoSuchAlgorithmException, KeyManagementException,
KeyStoreException, UnrecoverableKeyException
{
super(null, null, null, null, null, (X509HostnameVerifier)null);
Cur_SSL_Context.init(null, new TrustManager[] { new X509_Trust_Manager() }, null);
}
@Override
public Socket createSocket(Socket socket, String host, int port,
boolean autoClose) throws IOException
{
return Cur_SSL_Context.getSocketFactory().createSocket(socket, host, port, autoClose);
}
@Override
public Socket createSocket() throws IOException
{
return Cur_SSL_Context.getSocketFactory().createSocket();
}
}
private static class X509_Trust_Manager implements X509TrustManager
{
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
// TODO Auto-generated method stub
}
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
// TODO Auto-generated method stub
}
public X509Certificate[] getAcceptedIssuers() {
// TODO Auto-generated method stub
return null;
}
};
}
Je ne sais pas quelles sont les spécificités D'Android pour les certificats ssl, mais il serait logique que Android n'accepte pas un certificat ssl auto-signé hors de question. J'ai trouvé ce post de forums android qui semble aborder le même problème: http://androidforums.com/android-applications/950-imap-self-signed-ssl-certificates.html
C'est un problème connu avec Android 2.x. J'ai été aux prises avec ce problème pendant une semaine jusqu'à ce que je tombe sur la question suivante, qui non seulement donne un bon arrière-plan du problème, mais fournit également une solution efficace et fonctionnelle sans trous de sécurité.
"pas d'erreur de certificat peer" dans Android 2.3 mais pas dans 4
pour une raison quelconque, la solution mentionnée pour httpClient ci-dessus n'a pas fonctionné pour moi. À la fin, j'ai pu le faire fonctionner en contournant correctement la méthode lors de la mise en œuvre de la classe custom SSLSocketFactory.
@Override
public Socket createSocket(Socket socket, String host, int port, boolean autoClose)
throws IOException, UnknownHostException
{
return sslFactory.createSocket(socket, host, port, autoClose);
}
@Override
public Socket createSocket() throws IOException {
return sslFactory.createSocket();
}
C'est comme ça que ça a fonctionné parfaitement pour moi. Vous pouvez voir la classe personnalisée complète et l'implémentation sur le thread suivant: http://blog.syedgakbar.com/2012/07/21/android-https-and-not-trusted-server-certificate-error /
je fais cette classe et j'ai trouvé
package com.example.fakessl;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import android.util.Log;
public class CertificadoAceptar {
private static TrustManager[] trustManagers;
public static class _FakeX509TrustManager implements
javax.net.ssl.X509TrustManager {
private static final X509Certificate[] _AcceptedIssuers = new X509Certificate[] {};
public void checkClientTrusted(X509Certificate[] arg0, String arg1)
throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] arg0, String arg1)
throws CertificateException {
}
public boolean isClientTrusted(X509Certificate[] chain) {
return (true);
}
public boolean isServerTrusted(X509Certificate[] chain) {
return (true);
}
public X509Certificate[] getAcceptedIssuers() {
return (_AcceptedIssuers);
}
}
public static void allowAllSSL() {
javax.net.ssl.HttpsURLConnection
.setDefaultHostnameVerifier(new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
javax.net.ssl.SSLContext context = null;
if (trustManagers == null) {
trustManagers = new javax.net.ssl.TrustManager[] { new _FakeX509TrustManager() };
}
try {
context = javax.net.ssl.SSLContext.getInstance("TLS");
context.init(null, trustManagers, new SecureRandom());
} catch (NoSuchAlgorithmException e) {
Log.e("allowAllSSL", e.toString());
} catch (KeyManagementException e) {
Log.e("allowAllSSL", e.toString());
}
javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(context
.getSocketFactory());
}
}
en code blanc ce
CertificadoAceptar ca = new CertificadoAceptar();
ca.allowAllSSL();
HttpsTransportSE Transport = new HttpsTransportSE("iphost or host name", 8080, "/WS/wsexample.asmx?WSDL", 30000);
Sources qui m'ont aidé à travailler avec mon certificat auto-signé sur mon serveur Apache AWS et me connecter avec HttpsURLConnection à partir de l'appareil android:
SSL sur AWS instance - amazon tutorial sur ssl
sécurité Android avec HTTPS et SSL - création de votre propre gestionnaire de confiance sur le client pour accepter votre certificat
création certificat auto-signé - script facile pour créer vos certificats
alors j'ai fait ce qui suit:
- S'est assuré que le serveur supporte https (sudo yum install-y mod24_ssl)
- mettez ce script dans un fichier
create_my_certs.sh
:
#!/bin/bash FQDN= # make directories to work from mkdir -p server/ client/ all/ # Create your very own Root Certificate Authority openssl genrsa \ -out all/my-private-root-ca.privkey.pem \ 2048 # Self-sign your Root Certificate Authority # Since this is private, the details can be as bogus as you like openssl req \ -x509 \ -new \ -nodes \ -key all/my-private-root-ca.privkey.pem \ -days 1024 \ -out all/my-private-root-ca.cert.pem \ -subj "/C=US/ST=Utah/L=Provo/O=ACME Signing Authority Inc/CN=example.com" # Create a Device Certificate for each domain, # such as example.com, *.example.com, awesome.example.com # NOTE: You MUST match CN to the domain name or ip address you want to use openssl genrsa \ -out all/privkey.pem \ 2048 # Create a request from your Device, which your Root CA will sign openssl req -new \ -key all/privkey.pem \ -out all/csr.pem \ -subj "/C=US/ST=Utah/L=Provo/O=ACME Tech Inc/CN=${FQDN}" # Sign the request from Device with your Root CA openssl x509 \ -req -in all/csr.pem \ -CA all/my-private-root-ca.cert.pem \ -CAkey all/my-private-root-ca.privkey.pem \ -CAcreateserial \ -out all/cert.pem \ -days 500 # Put things in their proper place rsync -a all/{privkey,cert}.pem server/ cat all/cert.pem > server/fullchain.pem # we have no intermediates in this case rsync -a all/my-private-root-ca.cert.pem server/ rsync -a all/my-private-root-ca.cert.pem client/
- Exécuter
bash create_my_certs.sh yourdomain.com
-
Place le certificats à leur place sur le serveur (vous pouvez trouver la configuration dans /etc/httpd/conf.d / ssl.conf). Tous ceux-ci doivent être mis:
SSLCertificateFile
SSLCertificateKeyFile
151980920" SSLCertificateChainFile
SSLCACertificateFile -
redémarrez httpd en utilisant
sudo service httpd restart
et assurez-vous que httpd démarre:
L'arrêt de httpd: [ OK ]
Démarrage de httpd: [OK ] -
Copie
my-private-root-ca.cert
de votre projet android actifs dossier -
Créer votre confiance manager:
SSLContext SSLContext;
CertificateFactory cf = CertificateFactory.getInstance ("X. 509"); InputStream caInput = cadre.getAssets ().open("mon-privé-root-ca.cert.pem"); Certificat ca; essayer { ca = cf.certificat général(caInput)); } enfin { caInput.proche(); }
// Create a KeyStore containing our trusted CAs String keyStoreType = KeyStore.getDefaultType(); KeyStore keyStore = KeyStore.getInstance(keyStoreType); keyStore.load(null, null); keyStore.setCertificateEntry("ca", ca); // Create a TrustManager that trusts the CAs in our KeyStore String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm); tmf.init(keyStore); // Create an SSLContext that uses our TrustManager SSLContext = SSLContext.getInstance("TLS"); SSSLContext.init(null, tmf.getTrustManagers(), null);
-
et faire la connexion en utilisant HttpsURLConnection:
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); connexion.setSSLSocketFactory (SSLContext.getSocketFactory());
-
c'est ça, essayez votre connexion https.
il suffit D'utiliser cette méthode comme votre HTTPClient:
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();
}
}