Bir https gönderimi yapıyorum ve bir ssl istisnası alıyorum Güvenilir değil sunucu sertifikası. Normal http yaparsam mükemmel bir şekilde çalışıyor. Sunucu sertifikasını bir şekilde kabul etmem gerekiyor mu?
Bir https gönderimi yapıyorum ve bir ssl istisnası alıyorum Güvenilir değil sunucu sertifikası. Normal http yaparsam mükemmel bir şekilde çalışıyor. Sunucu sertifikasını bir şekilde kabul etmem gerekiyor mu?
Yanıtlar:
Bir tahminde bulunuyorum, ancak gerçek bir el sıkışmanın gerçekleşmesini istiyorsanız, sertifikanızı android'e bildirmelisiniz. Ne olursa olsun kabul etmek istiyorsanız, Apache HTTP İstemcisi ile ihtiyacınız olanı elde etmek için bu sözde kodu kullanın:
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, javax.net.ssl.X509TrustManager'ı uygulayan bir sınıftır, ancak yöntemlerin hiçbiri aslında herhangi bir iş yapmaz, buradan bir örnek alın .
İyi şanslar!
FullX509TrustManager
Yaptığım şey bu. Artık sertifikayı kontrol etmiyor.
// 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();
}
}
ve
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
. Ben de değiştirilmesi denedi TLS
ile SSL
ancak yardımcı olmadı. Lütfen bana yardım et, Teşekkürler
Bu soruyu cevaplamaya çalışırken daha iyi bir eğitim buldum. Bununla birlikte, sertifika kontrolünden ödün vermek zorunda değilsiniz.
http://blog.crazybob.org/2010/02/android-trusting-ssl-certificates.html
* Bunu yazmadım ama Bob Lee'ye çalışması için teşekkürler
Crazybobs'a çok benzeyen blog yazıma da bakabilirsiniz.
Bu çözüm aynı zamanda sertifika kontrolünden ödün vermez ve güvenilir sertifikaları kendi anahtar deponuza nasıl ekleyeceğinizi açıklar.
http://blog.antoine.li/index.php/2010/10/android-trusting-ssl-certificates/
http://madurangasblogs.blogspot.in/2013/08/avoiding-javaxnetsslsslpeerunverifiedex.html
Maduranga'nın izniyle
Https kullanan bir uygulama geliştirirken, test sunucunuzun geçerli bir SSL sertifikası yoktur. Veya bazen web sitesi kendinden imzalı bir sertifika kullanıyor veya web sitesi ücretsiz SSL sertifikası kullanıyor. Bu nedenle HttpClient
, Apache kullanarak sunucuya bağlanmaya çalışırsanız , "eşin kimliği doğrulanmadı" şeklinde bir istisna alırsınız. Bir üretim yazılımındaki tüm sertifikalara güvenmek iyi bir uygulama olmasa da duruma göre bunu yapmanız gerekebilir. Bu çözüm, "eş kimliği doğrulanmamış" ın neden olduğu istisnayı çözer.
Ancak çözüme gitmeden önce, bunun bir üretim uygulaması için iyi bir fikir olmadığı konusunda sizi uyarmalıyım. Bu, bir güvenlik sertifikası kullanma amacını ihlal eder. Dolayısıyla, iyi bir sebebiniz yoksa veya bunun herhangi bir soruna yol açmayacağından eminseniz, bu çözümü kullanmayın.
Normalde böyle bir HttpClient
şey yaratırsınız.
HttpClient httpclient = new DefaultHttpClient();
Ancak HttpClient'i yaratma şeklinizi değiştirmelisiniz.
Öncelikle genişleyen bir sınıf oluşturmalısınız 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();
}
}
Sonra bunun gibi bir yöntem oluşturun.
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();
}
}
Daha sonra HttpClient
.
HttpClient httpclient = getNewHttpClient();
Bir giriş sayfasına bir gönderi isteği göndermeye çalışıyorsanız, kodun geri kalanı bu şekilde olacaktır.
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();
}
Html sayfasını InputStream'e alırsınız. Ardından geri dönen html sayfası ile istediğinizi yapabilirsiniz.
Ama burada bir sorunla karşılaşacaksınız. Çerezleri kullanarak bir oturumu yönetmek istiyorsanız, bunu bu yöntemle yapamazsınız. Çerezleri almak istiyorsanız, bunu bir tarayıcı aracılığıyla yapmanız gerekecektir. O zaman sadece siz tanımlama bilgilerini alacaksınız.
StartSSL veya Thawte sertifikası kullanıyorsanız, Froyo ve daha eski sürümler için başarısız olacaktır. Her sertifikaya güvenmek yerine daha yeni bir sürümün CAcert deposunu kullanabilirsiniz .
Bunların hiçbiri benim için işe yaramadı ( Thawte böceği tarafından da ağırlaştırıldı ). Sonunda Android'de Kendinden imzalı SSL kabulüyle düzeltildi ve Özel SSL işleme Android 2.2 FroYo'da çalışmayı durdurdu
Bu cevaplardan herhangi biri benim için işe yaramadı, bu yüzden burada herhangi bir sertifikaya güvenen kod var.
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;
}
};
}
SSL sertifikaları için Android özelliklerini bilmiyorum, ancak Android'in kendi kendine imzalanan bir ssl sertifikasını yarasadan kabul etmemesi mantıklı olacaktır. Bu gönderiyi aynı sorunu ele alıyor gibi görünen android forumlarından buldum: http://androidforums.com/android-applications/950-imap-self-signed-ssl-certificates.html
Bu, Android 2.x ile ilgili bilinen bir sorundur. Sadece sorunun iyi bir arka planını vermekle kalmayıp, aynı zamanda herhangi bir güvenlik açıkından yoksun çalışan ve etkili bir çözüm sağlayan aşağıdaki soru ile karşılaşana kadar bir hafta boyunca bu sorunla mücadele ediyordum.
Bazı nedenlerden dolayı, yukarıda httpClient için belirtilen çözüm benim için işe yaramadı. Sonunda, özel SSLSocketFactory sınıfını uygularken yöntemi doğru bir şekilde geçersiz kılarak çalışmasını sağlayabildim.
@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();
}
Bu benim için mükemmel bir şekilde çalıştı. Tam özel sınıfı ve uygulamayı şu başlıkta görebilirsiniz: http://blog.syedgakbar.com/2012/07/21/android-https-and-not-trusted-server-certificate-error/
Bu sınıfı yapıyorum ve buldum
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());
}
}
içinde beyaz kod bu
CertificadoAceptar ca = new CertificadoAceptar();
ca.allowAllSSL();
HttpsTransportSE Transport = new HttpsTransportSE("iphost or host name", 8080, "/WS/wsexample.asmx?WSDL", 30000);
AWS Apache sunucumda kendi kendine imzalanan sertifikamla çalışmama ve android cihazdan HttpsURLConnection ile bağlantı kurmama yardımcı olan kaynaklar:
AWS örneğinde
SSL - HTTPS ve SSL ile ssl Android Güvenliği üzerine amazon öğreticisi - kabul etmek için istemcide kendi güven yöneticinizi oluşturma sertifikanız
Kendinden imzalı sertifika oluşturma - sertifikalarınızı oluşturmak için kolay komut dosyası
Sonra şunu yaptım:
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.com
Sertifikaları sunucuda uygun yerlerine yerleştirin (yapılandırmayı /etc/httpd/conf.d/ssl.conf içinde bulabilirsiniz). Tüm bunlar ayarlanmalıdır:
SSLCertificateFile
SSLCertificateKeyFile
SSLCertificateChainFile
SSLCACertificateFile
Httpd'yi kullanarak yeniden başlatın sudo service httpd restart
ve httpd'nin başladığından emin olun:
httpd durduruluyor: [Tamam] httpd başlatılıyor
: [Tamam]
Kopya my-private-root-ca.cert
android proje varlıkları klasörüne
Güven yöneticinizi oluşturun:
SSLContext SSLContext;
CertificateFactory cf = CertificateFactory.getInstance ("X.509"); InputStream caInput = context.getAssets (). Open ("my-private-root-ca.cert.pem"); Sertifika ca; {ca = cf.generateCertificate (caInput) deneyin; } son olarak {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);
Ve bağlantıyı HttpsURLConnection kullanarak yapın:
HttpsURLConnection bağlantısı = (HttpsURLConnection) url.openConnection (); connection.setSSLSocketFactory (SSLContext.getSocketFactory ());
İşte bu, https bağlantınızı deneyin.
Bu yöntemi HTTPC istemciniz olarak kullanın:
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();
}
}