itsource

Https Connection Android

mycopycode 2022. 9. 3. 14:15
반응형

Https Connection Android

https 투고를 실행 중 신뢰할 수 없는 서버 인증서에서 ssl 예외 메시지가 나타납니다.정상적인 http를 실행하면 완벽하게 정상적으로 동작합니다.서버 증명서를 어떻게 해서든 받아 들여야 하나요?

이게 내가 하고 있는 일이야.증명서를 더 이상 확인하지 않습니다.

// 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();
    }
}

그리고.

    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();
    }

추측하고 있습니다만, 실제로 악수를 하고 싶다면, 당신의 증명서를 안드로이드에 알려야 합니다.어떤 경우에도 그대로 받아들이려면 다음 의사 코드를 사용하여 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);

커스텀 SSLSocket Factory:

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 
}

풀X509TrustManager는 javax.net.ssl을 구현하는 클래스입니다.X509TrustManager는 실제로 어떤 작업도 수행하지 않습니다.여기서 샘플을 입수해 주세요.

행운을 빕니다.

이 질문에 답하려다 더 나은 튜토리얼을 발견했습니다.이를 통해 인증서 검사를 손상시킬 필요가 없습니다.

http://blog.crazybob.org/2010/02/android-trusting-ssl-certificates.html

*이 글을 쓴 것은 아니지만, Bob Lee의 노고에 감사드립니다.

제 블로그 기사도 보실 수 있습니다. 크레이지봇과 매우 비슷합니다.

이 솔루션에서는 증명서 체크에 영향을 주지 않고 자신의 키스토어에 신뢰할 수 있는 증명서를 추가하는 방법도 설명합니다.

http://blog.antoine.li/index.php/2010/10/android-trusting-ssl-certificates/

http://madurangasblogs.blogspot.in/2013/08/avoiding-javaxnetsslsslpeerunverifiedex.html

마두랑가

https를 사용하는 응용 프로그램을 개발할 때 테스트 서버에 유효한 SSL 인증서가 없습니다.또는 웹 사이트가 자체 서명된 인증서를 사용하거나 웹 사이트가 무료 SSL 인증서를 사용하는 경우가 있습니다. Apache를 에 HttpClient authenticated 「peer not authenticated」라고 하는 됩니다.실가동 소프트웨어의 모든 증명서를 신뢰하는 것은 좋은 방법은 아니지만 상황에 따라서는 신뢰해야 할 수도 있습니다.피어가 인증되지 않았습니다.

하지만 솔루션을 시작하기 전에, 이것은 실제 가동 애플리케이션에는 좋은 생각이 아니라는 것을 경고해야 합니다.이는 보안 증명서를 사용하는 목적에 위배됩니다.따라서 정당한 이유가 없거나 문제가 발생하지 않을 것으로 확신하는 경우에는 이 솔루션을 사용하지 마십시오.

으로는 「」를 합니다.HttpClient이것처럼.

HttpClient httpclient = new DefaultHttpClient();

단, HttpClient 작성 방법을 변경해야 합니다.

.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();
    }
}

그런 다음 다음과 같은 방법을 만듭니다.

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();
     }
}

'보다 낫다'를 수 .HttpClient.

HttpClient httpclient = getNewHttpClient();

로그인 페이지에 투고 요구를 송신하려고 하면, 그 외의 코드는 다음과 같습니다.

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 페이지를 InputStream으로 가져옵니다.그러면 반환된 html 페이지에서 원하는 작업을 수행할 수 있습니다.

하지만 여기서 당신은 문제에 직면할 것이다.쿠키를 사용하여 세션을 관리하는 경우 이 방법으로는 세션을 관리할 수 없습니다.쿠키를 가져오려면 브라우저를 통해 쿠키를 가져와야 합니다.그러면 너만 쿠키를 받을 수 있어.

Start를 사용하는 경우SSL 또는 Thawte 인증서는 Froyo 이전 버전에서는 실패합니다.모든 인증서를 신뢰하는 대신 새 버전의 CAcert 저장소를 사용할 수 있습니다.

이것들 중 어느 것도 나에게 효과가 없었다(Thawte 벌레에 의해서도).결국 Android에서 자체 서명 SSL 허용으로 수정되었고 Android 2.2 FroYo에서 커스텀 SSL 처리가 중지되었습니다.

이 답변들 중 어느 것도 제게는 효과가 없었습니다.따라서 여기 증명서를 신뢰하는 코드가 있습니다.

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 인증서에 대한 Android의 자세한 내용은 알 수 없지만, Android가 즉시 자체 서명된 ssl 인증서를 받아들이지 않는 것은 타당합니다.같은 문제에 대처하고 있는 것 같은 이 투고를 안드로이드 포럼에서 찾았습니다.http://androidforums.com/android-applications/950-imap-self-signed-ssl-certificates.html

이것은 Android 2.x에서 이미 알려진 문제입니다.저는 일주일 동안 이 문제에 대해 고민하다가 다음과 같은 질문을 받았습니다.이 질문에 대한 배경은 좋을 뿐만 아니라 보안상의 허점이 없는 효과적이고 효과적인 솔루션을 제공합니다.

Android 2.3에서는 'No peer certificate' 오류가 발생하지만 4에서는 그렇지 않습니다.

어떤 이유에서인지 위의 httpClient에 대해 언급한 솔루션은 나에게 효과가 없었습니다.최종적으로 커스텀 SSL Socket Factory 클래스를 실장할 때 메서드를 올바르게 오버라이드함으로써 동작시킬 수 있었습니다.

@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();
}

이게 나한테 딱 맞는 방법이야.완전한 커스텀클래스와 실장은 다음 스레드에서 확인할 수 있습니다.http://blog.syedgakbar.com/2012/07/21/android-https-and-not-trusted-server-certificate-error/

나는 이 수업을 만들고 발견했다.

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());
    }
}

당신의 코드 화이트는 이것입니다.

CertificadoAceptar ca = new CertificadoAceptar();
ca.allowAllSSL();
HttpsTransportSE Transport = new HttpsTransportSE("iphost or host name", 8080, "/WS/wsexample.asmx?WSDL", 30000);

AWS Apache 서버에서 자체 서명된 인증서로 작업하고 Https와 연결하는 데 도움이 되는 소스URLAndroid 장치에서 연결:

aWS 인스턴스의 SSL - ssl의 amazon 튜토리얼
HTTPS 및 SSL을 사용하는 Android 보안 - 인증서를 수락하기 위해 클라이언트에 자체 신뢰 관리자 만들기
자체 서명된 인증서 생성 - 인증서 생성을 위한 간단한 스크립트

그리고 다음 작업을 수행했습니다.

  1. 서버가 https를 지원하는지 확인(sudo yum install -y mod24_ssl)
  2. 이 스크립트를 파일에 저장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/
  1. 달려.bash create_my_certs.sh yourdomain.com
  2. 서버의 적절한 장소에 증명서를 배치합니다( /etc/httpd/conf.d/ssl.conf 에 설정이 있습니다).이 모든 것을 설정할 필요가 있습니다.
    SSLCertificate File(SSLCertificate File)
    SSLCertificateKeyFile
    SSLCertificate Chain File
    SSLCACertificate File(SSLCACertificate File)

  3. 를 사용하여 httpd를 재시작sudo service httpd restarthttpd 가 기동하고 있는 것을 확인합니다.
    httpd 중지 중: [OK]
    시작 httpd: [OK]

  4. 알았다.my-private-root-ca.certAndroid 프로젝트 자산 폴더에 저장

  5. 트러스트 매니저를 만듭니다.

    SSLContext SSLContext

    CertificateFactory cf = CertificateFactory.getInstance("X.509");InputStream caInput = context.getAssets().open("my-private-root-ca.cert.pem"); 인증서 CA; { ca = cf.generateCertificate(caInput); }, 마침내 { 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);
    
  6. Https를 사용하여 접속합니다.URL연결:

    HttpsURL Connection 연결 =(Https)URL Connection)url.open Connection(); 연결.setSSLSocketFactory(SSLContext.getSocketFactory());

  7. 이상입니다. https 접속을 시도합니다.

아마 이런 걸 시도해 볼 수 있을 거예요.이것은 나에게 도움이 되었다.

    SslContextFactory sec = new SslContextFactory();
    sec.setValidateCerts(false);
    sec.setTrustAll(true);

    org.eclipse.jetty.websocket.client.WebSocketClient client = new WebSocketClient(sec);

이 메서드를 HTTP Client로 사용합니다.

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();
    }
}

언급URL : https://stackoverflow.com/questions/995514/https-connection-android

반응형