如何使用HttpsUrlConnection代替DefaultHttpClient

6

DefaultHttpClient、ThreadSafeClientConnManager、HttpParams、HttpProtocolParams、SchemeRegistry、SSLSocketFactory和HttpResponse已经被弃用。

我尝试使用HttpsUrlConnection,但是我对它们感到困惑。

protected Gson gson;
private ThreadSafeClientConnManager threadSafeClientConnManager;
private DefaultHttpClient client;

AbstractServiceApi() {

    // sets up parameters
    HttpParams params = new BasicHttpParams();
    HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
    HttpProtocolParams.setContentCharset(params, ENCODING);
    HttpConnectionParams.setConnectionTimeout(params, 95 * 1000);
    HttpConnectionParams.setSoTimeout(params, 95 * 1000);
    HttpConnectionParams.setStaleCheckingEnabled(params, false);
    params.setBooleanParameter("http.protocol.expect-continue", false);

    // registers schemes for both http and https
    SchemeRegistry registry = new SchemeRegistry();
    registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
    SSLSocketFactory sslSocketFactory = SSLSocketFactory.getSocketFactory();
    sslSocketFactory.setHostnameVerifier(SSLSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
    registry.register(new Scheme("https", sslSocketFactory, 443));

    threadSafeClientConnManager = new ThreadSafeClientConnManager(params, registry);
    client = new DefaultHttpClient(threadSafeClientConnManager, params);
    gson = new Gson();
}

我没有keystore。

https://developer.android.com/reference/javax/net/ssl/HttpsURLConnection.html
   KeyStore keyStore = ...;
   String algorithm = TrustManagerFactory.getDefaultAlgorithm();
   TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
   tmf.init(keyStore);

   SSLContext context = SSLContext.getInstance("TLS");
   context.init(null, tmf.getTrustManagers(), null);

   URL url = new URL("https://www.example.com/");
   HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
   urlConnection.setSSLSocketFactory(context.getSocketFactory());
   InputStream in = urlConnection.getInputStream();

有人能帮助我吗?

4个回答

9
这是我的解决方案。
private HttpsURLConnection urlConnection;
private CookieManager cookieManager;

private HttpsURLConnection getConnection(String url) throws MalformedURLException {
    URL request_url = new URL(url);
    try {
        if (!isHttps()) {
            throw new ConnectException("you have to use SSL certifacated url!");
        }
        urlConnection = (HttpsURLConnection) request_url.openConnection();
        urlConnection.setRequestMethod("POST");
        urlConnection.setReadTimeout(95 * 1000);
        urlConnection.setConnectTimeout(95 * 1000);
        urlConnection.setDoInput(true);
        urlConnection.setRequestProperty("Accept", "application/json");
        urlConnection.setRequestProperty("X-Environment", "android");

        /** Cookie Sets... */
        String cookie = cookieManager.getCookie(urlConnection.getURL().toString());
        cookieManager = CookieManager.getInstance();
        if (cookie != null)
            urlConnection.setRequestProperty("Cookie", cookie);

        List<String> cookieList = urlConnection.getHeaderFields().get("Set-Cookie");
        if (cookieList != null) {
            for (String cookieTemp : cookieList) {
                cookieManager.setCookie(urlConnection.getURL().toString(), cookieTemp);
            }
        }
        /** Cookie Sets... */

        urlConnection.setHostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                /** if it necessarry get url verfication */
                //return HttpsURLConnection.getDefaultHostnameVerifier().verify("your_domain.com", session);
                return true;
            }
        });
        urlConnection.setSSLSocketFactory((SSLSocketFactory) SSLSocketFactory.getDefault());


        urlConnection.connect();

    } catch (IOException e) {
        e.printStackTrace();
    }

    return urlConnection;
}

为什么只返回 true?这不意味着您没有确认域已经验证吗? - portfoliobuilder
这只是一个示例。如果需要,请使用前面被注释的行。 - Kaloglu

7
您可以使用HttpURLConnection(http://developer.android.com/reference/java/net/HttpURLConnection.html)进行https通信。我理解您是用已知证书与Web服务器通信。在这种情况下,它看起来像是:
    public static final int CONNECTON_TIMEOUT_MILLISECONDS = 60000;

public static String executeGetHttpRequest(final String path) throws ClientProtocolException, IOException {
    String result = null;
    HttpURLConnection urlConnection = null;
    try {
        URL url = new URL(path);
        urlConnection = (HttpURLConnection) url.openConnection();
        urlConnection.setConnectTimeout(CONNECTON_TIMEOUT_MILLISECONDS);
        urlConnection.setReadTimeout(CONNECTON_TIMEOUT_MILLISECONDS);
        result = readStream(urlConnection.getInputStream());
    } finally {
        if (urlConnection != null) {
            urlConnection.disconnect();
        }
    }
    return result;
}

private static String readStream(InputStream is) throws IOException {
    final BufferedReader reader = new BufferedReader(new InputStreamReader(is, Charset.forName("US-ASCII")));
    StringBuilder total = new StringBuilder();
    String line;
    while ((line = reader.readLine()) != null) {
        total.append(line);
    }
    if (reader != null) {
        reader.close();
    }
    return total.toString();
}

这是一个工作样例。您可以查看这篇好文章,其中描述了不同的情况 - http://developer.android.com/training/articles/security-ssl.html


7

对于HttpsUrlConnection,您可以参考以下示例代码:

    private TrustManager[] getWrappedTrustManagers(TrustManager[] trustManagers) {
        final X509TrustManager originalTrustManager = (X509TrustManager) trustManagers[0];
        return new TrustManager[]{
                new X509TrustManager() {
                    public X509Certificate[] getAcceptedIssuers() {
                        return originalTrustManager.getAcceptedIssuers();
                    }

                    public void checkClientTrusted(X509Certificate[] certs, String authType) {
                        try {
                            originalTrustManager.checkClientTrusted(certs, authType);
                        } catch (CertificateException ignored) {
                        }
                    }

                    public void checkServerTrusted(X509Certificate[] certs, String authType) {
                        try {
                            originalTrustManager.checkServerTrusted(certs, authType);
                        } catch (CertificateException ignored) {
                        }
                    }
                }
        };
    }

    private SSLSocketFactory getSSLSocketFactory() {
        try {
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            InputStream caInput = getResources().openRawResource(R.raw.your_cert);
            Certificate ca = cf.generateCertificate(caInput);
            caInput.close();

            KeyStore keyStore = KeyStore.getInstance("BKS");
            keyStore.load(null, null);
            keyStore.setCertificateEntry("ca", ca);

            String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
            TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
            tmf.init(keyStore);

            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, getWrappedTrustManagers(tmf.getTrustManagers()), null);                

            return sslContext.getSocketFactory();
        } catch (Exception e) {
            return HttpsURLConnection.getDefaultSSLSocketFactory();
        }
    }

    private class GETRequest extends AsyncTask<Void, Void, String> {
        @Override
        protected String doInBackground(Void... params) {
            try {
                URL url = new URL("https://your_server_url");
                String token = "rbkY34HnL...";
                HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
                urlConnection.setSSLSocketFactory(getSSLSocketFactory());
                urlConnection.setHostnameVerifier(new HostnameVerifier() {
                    @Override
                    public boolean verify(String hostname, SSLSession session) {
//                        return true;
                        HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier();
                        return hv.verify("your_domain.com", session);
                    }
                });    
                urlConnection.setRequestProperty("Authorization", "Bearer " + token);
                urlConnection.connect();
                InputStream inputStream;
                if (urlConnection.getResponseCode() != HttpURLConnection.HTTP_OK) {
                    inputStream = urlConnection.getErrorStream();
                } else {
                    inputStream = urlConnection.getInputStream();
                }
                return String.valueOf(urlConnection.getResponseCode()) + " " + urlConnection.getResponseMessage() + "\r\n" + parseStream(inputStream);
            } catch (Exception e) {
                return e.toString();
            }
        }

        @Override
        protected void onPostExecute(String response) {
            super.onPostExecute(response);
            // do something...
        }
    }

希望能对您有所帮助!

如果您想在开发过程中忽略SSL,您也可以阅读我的答案,网址为https://dev59.com/G47da4cB1Zd3GeqP9itu#32051885。 - BNK

0

你可以通过以下方式使用HttpURLConnection

URL url = new URL(urlString);

    HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
    urlConnection.setRequestMethod("GET");
    urlConnection.connect();

    // Read the input stream into a String
    InputStream inputStream = urlConnection.getInputStream();
    StringBuffer buffer = new StringBuffer();
    if (inputStream == null) {
        // Nothing to do.
        return null;
    }

    BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
    String line;
    while ((line = reader.readLine()) != null) {
        buffer.append(line + "\n");
    }

    if (buffer.length() == 0) {
        return null;
    }

    String stringResult = buffer.toString();

我需要Https协议。HttpUrlConnection可以使用。 - Kaloglu
{btsdaf} - Joubert Vasconcelos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接