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 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?
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:
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 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!
FullX509TrustManager
Inilah yang saya lakukan. Itu tidak memeriksa sertifikat lagi.
// 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();
}
}
dan
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();
}
javax.net.ssl.SSLException: Received fatal alert: bad_record_mac. Saya juga mencoba mengganti TLSdengan SSLtetapi tidak membantu. Tolong bantu saya, Terima kasih
Saat 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
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/
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 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.
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();
}
}
Kemudian buat metode seperti ini.
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();
}
}
Kemudian Anda dapat membuat file HttpClient.
HttpClient httpclient = getNewHttpClient();
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 = 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();
}
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.
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
Semua jawaban ini tidak berhasil untuk saya, jadi inilah kode yang mempercayai sertifikat apa pun.
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;
}
};
}
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
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
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.
@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();
}
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/
Saya membuat kelas ini dan menemukan
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());
}
}
dalam kode Anda putih ini
CertificadoAceptar ca = new CertificadoAceptar();
ca.allowAllSSL();
HttpsTransportSE Transport = new HttpsTransportSE("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:
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:#!/bin/bash FQDN=$1 # 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/
bash create_my_certs.sh yourdomain.comTempatkan 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
Buat 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 (); }
// 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);Dan buat koneksi menggunakan HttpsURLConnection:
Koneksi HttpsURLConnection = (HttpsURLConnection) url.openConnection (); connection.setSSLSocketFactory (SSLContext.getSocketFactory ());
Itu saja, coba koneksi https Anda.
Cukup gunakan metode ini sebagai HTTPClient Anda:
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();
}
}