Saya melakukan posting https dan saya mendapatkan pengecualian dari pengecualian ssl Sertifikat server tidak tepercaya. Jika saya melakukan http normal itu berfungsi dengan baik. Apakah saya harus menerima sertifikat server?
Saya sedang menebak, tetapi jika Anda ingin jabat tangan yang sebenarnya terjadi, Anda harus memberi tahu android tentang sertifikat Anda. Jika Anda hanya ingin menerima apa pun yang terjadi, gunakan pseudo-code ini untuk mendapatkan apa yang Anda butuhkan dengan Apache HTTP Client:
publicclassCustomSSLSocketFactoryextends org.apache.http.conn.ssl.SSLSocketFactory{privateSSLSocketFactory FACTORY =HttpsURLConnection.getDefaultSSLSocketFactory ();publicCustomSSLSocketFactory(){super(null);try{SSLContext context =SSLContext.getInstance ("TLS");TrustManager[] tm =newTrustManager[]{newFullX509TrustManager()};
context.init (null, tm,newSecureRandom());
FACTORY = context.getSocketFactory ();}catch(Exception e){
e.printStackTrace();}}publicSocket createSocket()throwsIOException{return FACTORY.createSocket();}// TODO: add other methods like createSocket() and getDefaultCipherSuites().// Hint: they all just make a call to member FACTORY }
FullX509TrustManager adalah kelas yang mengimplementasikan javax.net.ssl.X509TrustManager, namun tidak ada metode yang benar-benar melakukan pekerjaan apa pun, dapatkan contoh di sini .
return FACTORY.createSocket (); sedang mengalami masalah. Soket yang dibuat memberikan pengecualian Pointer nol pada eksekusi (). Juga, saya perhatikan, ada 2 kelas SocketFactory. 1. org.apache.http.conn.ssl.SSLSocketFactory dan 2. javax.net.ssl.SSLSocketFactory
Codevalley
2
Hai Nate, sepertinya ini berguna untuk situasi saya. Namun, saya mengalami beberapa masalah dengan pembuatan CustomSSLSocketFactory. Kelas apa yang seharusnya diperluas? Atau antarmuka apa yang seharusnya diimplementasikan? Saya telah bereksperimen dengan: javax.net.SocketFactory, javax.net.ssl.SSLSocketFactory, org.apache.http.conn.scheme.SocketFactory, semuanya memaksa penerapan metode lain ... Jadi, secara umum, apa ruang nama kelas yang digunakan dalam kode Anda? Terima kasih. :)
Cephron
2
Tidak berfungsi untuk saya, memberi saya kesalahan sertifikat server Tidak tepercaya yang sama.
Omar Rehman
1
bagaimana saya bisa mendapatkan kelas iniFullX509TrustManager
RajaReddy PolamReddy
89
Inilah yang saya lakukan. Itu tidak memeriksa sertifikat lagi.
// always verify the host - dont check for certificatefinalstaticHostnameVerifier DO_NOT_VERIFY =newHostnameVerifier(){publicboolean verify(String hostname,SSLSession session){returntrue;}};/**
* Trust every server - dont check for any certificate
*/privatestaticvoid trustAllHosts(){// Create a trust manager that does not validate certificate chainsTrustManager[] trustAllCerts =newTrustManager[]{new X509TrustManager(){public java.security.cert.X509Certificate[] getAcceptedIssuers(){returnnew java.security.cert.X509Certificate[]{};}publicvoid checkClientTrusted(X509Certificate[] chain,String authType)throwsCertificateException{}publicvoid checkServerTrusted(X509Certificate[] chain,String authType)throwsCertificateException{}}};// Install the all-trusting trust managertry{SSLContext sc =SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts,new java.security.SecureRandom());HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());}catch(Exception e){
e.printStackTrace();}}
Ini terlihat bagus! Saya menggunakan WebView, bagaimanapun, dan hanya perlu terhubung ke server https untuk tujuan pengujian. (Klien tidak dapat menyediakan satu dengan FQDN yang cocok, mereka juga tidak dapat mengujinya di http.) Apakah ada cara untuk mengatasi ini saat menggunakan WebView? Apakah saya hanya meletakkan kode ini di Aktivitas tempat WebView berada dan "berfungsi begitu saja?" (Tidak curiga… ??)
Joe D'Andrea
Saya mencoba menggunakan solusi itu selangkah demi selangkah dan saya mendapatkan pengecualian seperti itu: 07-25 12: 35: 25.941: WARN / System.err (24383): java.lang.ClassCastException: org.apache.harmony.luni .internal.net.www.protocol.http.HttpURLConnectionImpl di tempat saya mencoba membuka koneksi ... ada ide mengapa ??
Robert
1
Hai, saya melakukan seperti yang disarankan oleh Anda, tetapi saya mendapatkan pengecualian sebagai javax.net.ssl.SSLException: Received fatal alert: bad_record_mac. Saya juga mencoba mengganti TLSdengan SSLtetapi tidak membantu. Tolong bantu saya, Terima kasih
devsri
40
Meskipun ini bagus selama fase pengembangan, Anda harus menyadari fakta bahwa ini memungkinkan siapa saja untuk melakukan MITM koneksi aman Anda dengan memalsukan sertifikat SSL acak, yang membuat koneksi Anda tidak aman lagi. Lihat pertanyaan ini untuk melihat cara yang benar, di sini untuk melihat cara menerima sertifikat, dan terakhir ini untuk mempelajari cara menambahkannya ke keystore.
cimnine
2
Anda tidak boleh menggunakan merekomendasikan atau memposting kode ini. Ini sangat tidak aman. Anda harus menyelesaikan masalah yang sebenarnya.
Marquis dari Lorne
33
Saat mencoba menjawab pertanyaan ini saya menemukan tutorial yang lebih baik. Dengannya Anda tidak perlu membahayakan pemeriksaan sertifikat.
Inilah jawaban yang tepat. Saya membuat posting pembaruan yang menunjukkan cara menangani CA yang tidak terdaftar karena saya mendapatkan kesalahan PeerCertificate. Lihat di sini: blog.donnfelker.com/2011/06/13/…
Donn Felker
6
Anda juga bisa melihat artikel blog saya, sangat mirip dengan crazybobs.
Solusi ini juga tidak mengganggu pemeriksaan sertifikat dan menjelaskan cara menambahkan sertifikat tepercaya di keystore Anda sendiri.
Saat mengembangkan aplikasi yang menggunakan https, server pengujian Anda tidak memiliki sertifikat SSL yang valid. Atau terkadang situs web menggunakan sertifikat yang ditandatangani sendiri atau situs web menggunakan sertifikat SSL gratis. Jadi jika Anda mencoba untuk terhubung ke server menggunakan Apache HttpClient, Anda akan mendapatkan pengecualian yang mengatakan bahwa "rekan tidak diautentikasi". Meskipun bukan praktik yang baik untuk mempercayai semua sertifikat dalam perangkat lunak produksi, Anda mungkin harus melakukannya sesuai situasi. Solusi ini menyelesaikan pengecualian yang disebabkan oleh "rekan tidak diautentikasi".
Tetapi sebelum kita pergi ke solusi, saya harus memperingatkan Anda bahwa ini bukanlah ide yang baik untuk aplikasi produksi. Ini akan melanggar tujuan penggunaan sertifikat keamanan. Jadi, kecuali Anda memiliki alasan yang baik atau jika Anda yakin ini tidak akan menimbulkan masalah, jangan gunakan solusi ini.
Biasanya Anda membuat HttpClientseperti ini.
HttpClient httpclient = new DefaultHttpClient();
Tetapi Anda harus mengubah cara Anda membuat HttpClient.
Pertama, Anda harus membuat class extending org.apache.http.conn.ssl.SSLSocketFactory.
Jika Anda mencoba mengirim permintaan posting ke halaman login, sisa kode akan seperti ini.
private URI url =new URI("url of the action of the form");HttpPost httppost =newHttpPost(url);List<NameValuePair> nameValuePairs =newArrayList<NameValuePair>();
nameValuePairs.add(newBasicNameValuePair("username","user"));
nameValuePairs.add(newBasicNameValuePair("password","password"));try{
httppost.setEntity(newUrlEncodedFormEntity(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();}
Anda mendapatkan halaman html ke InputStream. Kemudian Anda dapat melakukan apapun yang Anda inginkan dengan halaman html yang dikembalikan.
Tapi di sini Anda akan menghadapi masalah. Jika Anda ingin mengelola sesi menggunakan cookie, Anda tidak akan dapat melakukannya dengan metode ini. Jika Anda ingin mendapatkan cookie, Anda harus melakukannya melalui browser. Maka hanya Anda yang akan menerima cookie.
Jika Anda menggunakan sertifikat StartSSL atau Thawte, itu akan gagal untuk Froyo dan versi yang lebih lama. Anda dapat menggunakan repositori CAcert versi yang lebih baru daripada memercayai setiap sertifikat.
Saya tidak tahu tentang spesifikasi Android untuk sertifikat ssl, tetapi masuk akal bahwa Android tidak akan menerima sertifikat ssl yang ditandatangani sendiri secara langsung. Saya menemukan posting ini dari forum android yang sepertinya membahas masalah yang sama:
http://androidforums.com/android-applications/950-imap-self-signed-ssl-certificates.html
Seperti yang saya katakan, saya tidak tahu secara spesifik Android tetapi saya hari Anda harus memberi tahu platform apa sertifikat ssl dari server yang Anda sambungkan. Itu jika Anda menggunakan sertifikat yang ditandatangani sendiri yang tidak dikenali oleh platform. Kelas SslCertificate mungkin akan membantu: developer.android.com/reference/android/net/http/… Saya akan membahasnya nanti hari ini ketika saya punya lebih banyak waktu.
Matti Lyra
1
Ini adalah masalah yang diketahui dengan Android 2.x. Saya berjuang dengan masalah ini selama seminggu sampai saya menemukan pertanyaan berikut, yang tidak hanya memberikan latar belakang masalah yang baik tetapi juga memberikan solusi yang berfungsi dan efektif tanpa celah keamanan.
Untuk beberapa alasan, solusi yang disebutkan untuk httpClient di atas tidak berhasil untuk saya. Pada akhirnya saya bisa membuatnya bekerja dengan benar menimpa metode saat menerapkan kelas SSLSocketFactory kustom.
CertificadoAceptar ca =newCertificadoAceptar();
ca.allowAllSSL();HttpsTransportSETransport=newHttpsTransportSE("iphost or host name",8080,"/WS/wsexample.asmx?WSDL",30000);
Sumber yang membantu saya mulai bekerja dengan sertifikat yang saya tandatangani sendiri di server AWS Apache saya dan terhubung dengan HttpsURLConnection dari perangkat android:
Pastikan server mendukung https (sudo yum install -y mod24_ssl)
Letakkan skrip ini dalam sebuah file create_my_certs.sh:
#!/bin/bash
FQDN=$1
# make directories to work from
mkdir -p server/ client/ all/#Create your very own RootCertificateAuthority
openssl genrsa \
-out all/my-private-root-ca.privkey.pem \
2048#Self-sign your RootCertificateAuthority#Sincethis 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 DeviceCertificatefor 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 thiscase
rsync -a all/my-private-root-ca.cert.pem server/
rsync -a all/my-private-root-ca.cert.pem client/
Lari bash create_my_certs.sh yourdomain.com
Tempatkan sertifikat di tempat yang tepat di server (Anda dapat menemukan konfigurasi di /etc/httpd/conf.d/ssl.conf). Semua ini harus disetel:
SSLCertificateFile
SSLCertificateKeyFile
SSLCertificateChainFile
SSLCACertificateFile
Mulai ulang httpd menggunakan sudo service httpd restartdan pastikan httpd dimulai:
Menghentikan httpd: [Oke]
Memulai httpd: [Oke]
Salin my-private-root-ca.certke folder aset proyek android Anda
// Create a KeyStore containing our trusted CAsString 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 KeyStoreString tmfAlgorithm =TrustManagerFactory.getDefaultAlgorithm();TrustManagerFactory tmf =TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);// Create an SSLContext that uses our TrustManagerSSLContext=SSLContext.getInstance("TLS");SSSLContext.init(null, tmf.getTrustManagers(),null);
Jawaban:
Saya sedang menebak, tetapi jika Anda ingin jabat tangan yang sebenarnya terjadi, Anda harus memberi tahu android tentang sertifikat Anda. Jika Anda hanya ingin menerima apa pun yang terjadi, gunakan pseudo-code ini untuk mendapatkan apa yang Anda butuhkan dengan Apache HTTP Client:
CustomSSLSocketFactory:
FullX509TrustManager adalah kelas yang mengimplementasikan javax.net.ssl.X509TrustManager, namun tidak ada metode yang benar-benar melakukan pekerjaan apa pun, dapatkan contoh di sini .
Semoga berhasil!
sumber
FullX509TrustManager
Inilah yang saya lakukan. Itu tidak memeriksa sertifikat lagi.
dan
sumber
javax.net.ssl.SSLException: Received fatal alert: bad_record_mac
. Saya juga mencoba menggantiTLS
denganSSL
tetapi tidak membantu. Tolong bantu saya, Terima kasihSaat mencoba menjawab pertanyaan ini saya menemukan tutorial yang lebih baik. Dengannya Anda tidak perlu membahayakan pemeriksaan sertifikat.
http://blog.crazybob.org/2010/02/android-trusting-ssl-certificates.html
* Saya tidak menulis ini tetapi terima kasih kepada Bob Lee untuk pekerjaannya
sumber
Anda juga bisa melihat artikel blog saya, sangat mirip dengan crazybobs.
Solusi ini juga tidak mengganggu pemeriksaan sertifikat dan menjelaskan cara menambahkan sertifikat tepercaya di keystore Anda sendiri.
http://blog.antoine.li/index.php/2010/10/android-trusting-ssl-certificates/
sumber
http://madurangasblogs.blogspot.in/2013/08/avoiding-javaxnetsslsslpeerunverifiedex.html
Atas kebaikan Maduranga
Saat mengembangkan aplikasi yang menggunakan https, server pengujian Anda tidak memiliki sertifikat SSL yang valid. Atau terkadang situs web menggunakan sertifikat yang ditandatangani sendiri atau situs web menggunakan sertifikat SSL gratis. Jadi jika Anda mencoba untuk terhubung ke server menggunakan Apache
HttpClient
, Anda akan mendapatkan pengecualian yang mengatakan bahwa "rekan tidak diautentikasi". Meskipun bukan praktik yang baik untuk mempercayai semua sertifikat dalam perangkat lunak produksi, Anda mungkin harus melakukannya sesuai situasi. Solusi ini menyelesaikan pengecualian yang disebabkan oleh "rekan tidak diautentikasi".Tetapi sebelum kita pergi ke solusi, saya harus memperingatkan Anda bahwa ini bukanlah ide yang baik untuk aplikasi produksi. Ini akan melanggar tujuan penggunaan sertifikat keamanan. Jadi, kecuali Anda memiliki alasan yang baik atau jika Anda yakin ini tidak akan menimbulkan masalah, jangan gunakan solusi ini.
Biasanya Anda membuat
HttpClient
seperti ini.HttpClient httpclient = new DefaultHttpClient();
Tetapi Anda harus mengubah cara Anda membuat HttpClient.
Pertama, Anda harus membuat class extending
org.apache.http.conn.ssl.SSLSocketFactory
.Kemudian buat metode seperti ini.
Kemudian Anda dapat membuat file
HttpClient
.HttpClient httpclient = getNewHttpClient();
Jika Anda mencoba mengirim permintaan posting ke halaman login, sisa kode akan seperti ini.
Anda mendapatkan halaman html ke InputStream. Kemudian Anda dapat melakukan apapun yang Anda inginkan dengan halaman html yang dikembalikan.
Tapi di sini Anda akan menghadapi masalah. Jika Anda ingin mengelola sesi menggunakan cookie, Anda tidak akan dapat melakukannya dengan metode ini. Jika Anda ingin mendapatkan cookie, Anda harus melakukannya melalui browser. Maka hanya Anda yang akan menerima cookie.
sumber
Jika Anda menggunakan sertifikat StartSSL atau Thawte, itu akan gagal untuk Froyo dan versi yang lebih lama. Anda dapat menggunakan repositori CAcert versi yang lebih baru daripada memercayai setiap sertifikat.
sumber
Tak satu pun dari ini berhasil untuk saya (diperburuk oleh bug Thawte juga). Akhirnya saya memperbaikinya dengan penerimaan SSL yang ditandatangani sendiri di Android dan penanganan SSL Khusus berhenti berfungsi di Android 2.2 FroYo
sumber
Semua jawaban ini tidak berhasil untuk saya, jadi inilah kode yang mempercayai sertifikat apa pun.
sumber
Saya tidak tahu tentang spesifikasi Android untuk sertifikat ssl, tetapi masuk akal bahwa Android tidak akan menerima sertifikat ssl yang ditandatangani sendiri secara langsung. Saya menemukan posting ini dari forum android yang sepertinya membahas masalah yang sama: http://androidforums.com/android-applications/950-imap-self-signed-ssl-certificates.html
sumber
Ini adalah masalah yang diketahui dengan Android 2.x. Saya berjuang dengan masalah ini selama seminggu sampai saya menemukan pertanyaan berikut, yang tidak hanya memberikan latar belakang masalah yang baik tetapi juga memberikan solusi yang berfungsi dan efektif tanpa celah keamanan.
Kesalahan 'Tidak ada sertifikat rekan' di Android 2.3 tetapi BUKAN di 4
sumber
Untuk beberapa alasan, solusi yang disebutkan untuk httpClient di atas tidak berhasil untuk saya. Pada akhirnya saya bisa membuatnya bekerja dengan benar menimpa metode saat menerapkan kelas SSLSocketFactory kustom.
Beginilah cara kerjanya dengan sempurna bagi saya. Anda dapat melihat kelas khusus lengkap dan menerapkannya di utas berikut: http://blog.syedgakbar.com/2012/07/21/android-https-and-not-trusted-server-certificate-error/
sumber
Saya membuat kelas ini dan menemukan
dalam kode Anda putih ini
sumber
Sumber yang membantu saya mulai bekerja dengan sertifikat yang saya tandatangani sendiri di server AWS Apache saya dan terhubung dengan HttpsURLConnection dari perangkat android:
SSL pada instance aws - tutorial amazon tentang ssl
Android Security dengan HTTPS dan SSL - membuat pengelola kepercayaan Anda sendiri pada klien untuk menerima sertifikat Anda
Membuat sertifikat yang ditandatangani sendiri - skrip mudah untuk membuat sertifikat Anda
Kemudian saya melakukan hal berikut:
create_my_certs.sh
:bash create_my_certs.sh yourdomain.com
Tempatkan sertifikat di tempat yang tepat di server (Anda dapat menemukan konfigurasi di /etc/httpd/conf.d/ssl.conf). Semua ini harus disetel:
SSLCertificateFile
SSLCertificateKeyFile
SSLCertificateChainFile
SSLCACertificateFile
Mulai ulang httpd menggunakan
sudo service httpd restart
dan pastikan httpd dimulai:Menghentikan httpd: [Oke]
Memulai httpd: [Oke]
Salin
my-private-root-ca.cert
ke folder aset proyek android AndaBuat pengelola kepercayaan Anda:
SSLContext SSLContext;
CertificateFactory cf = CertificateFactory.getInstance ("X.509"); InputStream caInput = context.getAssets (). Open ("my-private-root-ca.cert.pem"); Sertifikat ca; coba {ca = cf.generateCertificate (caInput); } akhirnya {caInput.close (); }
Dan buat koneksi menggunakan HttpsURLConnection:
Koneksi HttpsURLConnection = (HttpsURLConnection) url.openConnection (); connection.setSSLSocketFactory (SSLContext.getSocketFactory ());
Itu saja, coba koneksi https Anda.
sumber
Mungkin Anda bisa mencoba sesuatu seperti ini. Ini membantu saya
sumber
Cukup gunakan metode ini sebagai HTTPClient Anda:
sumber