Android使用自签名证书连接到服务器

时间:2014-02-28 00:10:42

标签: java android ssl self-signed

编辑:“下面的代码工作正常,没有错误,没有例外”

我知道关于这个话题的大量问题,以及谷歌让人想起的许多博客。我已经通读了它们,并设法提出了我要解释的内容。我的疑问在于“我的方法是否正确?它是否有任何副作用?”而另一个问题在我解释我的方法时会更好。

我遵循此Android.Developres tutorial的方法。

 System.setProperty("jsse.enableSNIExtension", "false");  
 //Java 7 introduced SNI (enabled by default). The server I use is
 // misconfigured I suppose and
 // it sends an "Unrecognized Name" warning in the SSL handshake
 // which breaks my web service.

// Load CA from an InputStream (CA would be saved in Raw file,
// and loaded as a raw resource)
    CertificateFactory cf = CertificateFactory.getInstance("X.509");
    InputStream caInput = new BufferedInputStream(new FileInputStream("PATH_TO_CERT.crt"));

    Certificate ca;
    try {
        ca = cf.generateCertificate(caInput);
    } finally {
        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 context = SSLContext.getInstance("TLS");
    context.init(null, tmf.getTrustManagers(), null);

 // Create all-trusting host name verifier 
    //  to avoid the following :
    //   java.security.cert.CertificateException: No name matching
    // This is because Java by default verifies that the certificate CN (Common Name) is
   // the same as host name in the URL. If they are not, the web service client fails.

     HostnameVerifier allHostsValid = new HostnameVerifier() {
        @Override
        public boolean verify(String arg0, SSLSession arg1) {
            return true;
        }
    };

    //Install it
    HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);


    // Tell the URLConnection to use a SocketFactory from our SSLContext
    URL url = new URL("https....");
            urlConnection.setSSLSocketFactory(context.getSocketFactory());

    try {

        HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
        urlConnection.setRequestMethod("GET");

        urlConnection.connect();

        switch(urlConnection.getResponseCode()){
        case 401:


            BufferedReader br = new BufferedReader(new InputStreamReader(urlConnection.getErrorStream()));
            StringBuilder sb = new StringBuilder();
            String line;
            while ((line = br.readLine()) != null) {
                sb.append(line+"\n");
            }
            br.close();

            System.out.println( sb.toString());

        }



    } catch (MalformedURLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (ProtocolException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }



}

以下是我的另一个问题:

InputStream caInput = new BufferedInputStream(new FileInputStream("PATH_TO_CERT.crt"));

您看到该方法强制我将certificate.crt预先加载到res文件夹中的原始文件中。有没有办法(我看过但已找到0个答案)连接到服务器并下载所述certificate.crt并将其保存在用户无法访问的私人文件夹中?

0 个答案:

没有答案