【问题标题】:how to make HTTPS calls using AsyncHttpClient?如何使用 AsyncHttpClient 进行 HTTPS 调用?
【发布时间】:2014-03-17 00:40:08
【问题描述】:

我使用 AsyncHttpClient link 进行 http 调用,但现在我们的服务器已迁移到 HTTPS,我收到异常 javax.net.ssl.SSLPeerUnverifiedException: No peer certificate 。 有没有人尝试过使用这个库进行 https 调用?

AsyncHttpClient 的初始化:-

AsyncHttpClient client = new AsyncHttpClient();
            PersistentCookieStore myCookieStore = new PersistentCookieStore(
                    getActivity());
            // List<Cookie> cookies = myCookieStore.getCookies();
            myCookieStore.clear();
            // cookies = myCookieStore.getCookies();
            client.setCookieStore(myCookieStore);

            client.get(loginUrl, new JsonHttpResponseHandler() {

                @Override
                public void onStart() {
                    super.onStart();
                    progressBar.setVisibility(View.VISIBLE);
                }

                @Override
                public void onFinish() {
                    super.onFinish();
                    progressBar.setVisibility(View.GONE);
                }

                @Override
                public void onSuccess(int statusCode, JSONObject userInfo) {
                    super.onSuccess(statusCode, userInfo);

                    String errorMsg = null;
                    try {
                        errorMsg = userInfo.getString("error");
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }

                    if (errorMsg != null) {
                        errorMsg = getActivity().getResources().getString(
                                R.string.loginFailure)
                                + "\nError: " + errorMsg;
                        tvLoginFailure.setText(errorMsg);
                        tvLoginFailure.setVisibility(View.VISIBLE);

                    } else {
                        Subscriber.setEmail(email);
                        Subscriber.setPassword(password);
                        LoginUtility.saveUserInfo(getActivity(), userInfo);

                        if (Subscriber.getStatus().contentEquals("ACTIVE")) {
                            Intent intent;
                            if (MyApplication.ottMode) {
                                intent = new Intent(getActivity(),
                                        OTTMainScreen.class);

                            } else {
                                intent = new Intent(getActivity(),
                                        MainActivity.class);
                                intent.putExtra("SIGNEDIN", true);
                            }
                            if (MyApplication.ottMode) {
                                Utility.playSound(getActivity());
                            }
                            startActivity(intent);
                            getActivity().finish();

                        } else if (Subscriber.getStatus().contentEquals(
                                "SUSPENDED")) {
                            try {
                                String suspendedReason = userInfo
                                        .getString("suspendreason");
                                if (suspendedReason != null
                                        && suspendedReason
                                                .contentEquals("NO_SUBSCRIPTION")) {

                                    new AlertDialog.Builder(getActivity())
                                            .setIcon(
                                                    android.R.drawable.ic_dialog_alert)
                                            .setTitle("Account Suspended")
                                            .setMessage(
                                                    "Your account doesn't have any active subscription. You need to subscribe to a Package before you can proceed.")
                                            .setPositiveButton(
                                                    "Subscribe",
                                                    new DialogInterface.OnClickListener() {
                                                        public void onClick(
                                                                DialogInterface dialog,
                                                                int which) {
                                                            recreatePackage();
                                                        }
                                                    })
                                            .setNegativeButton("Cancel", null)
                                            .show();

                                } else {
                                    // TODO
                                }
                            } catch (JSONException e) {
                                e.printStackTrace();
                            }

                        } else if (Subscriber.getStatus().contentEquals("INIT")) {
                            // TODO
                        }
                    }
                }

                @Override
                public void onFailure(int statusCode,
                        org.apache.http.Header[] headers, String responseBody,
                        Throwable e) {
                    super.onFailure(statusCode, headers, responseBody, e);
                    String msg = getActivity().getResources().getString(
                            R.string.loginFailure)
                            + "\nError: " + responseBody;
                    tvLoginFailure.setText(msg);
                    tvLoginFailure.setVisibility(View.VISIBLE);
                }
            });

【问题讨论】:

标签: android networking https android-async-http


【解决方案1】:

您也可以通过添加这一行来解决此问题。

asyncHttpClient.setSSLSocketFactory(MySSLSocketFactory.getFixedSocketFactory());

【讨论】:

  • 在使用 MySSLSocketFactory 时需要提一下:“警告!这会在每台设备上省略 SSL 证书验证,请谨慎使用。”
  • 这是一个比上面的更好的解决方案。但不幸的是,它并没有解决我的问题。我真的很喜欢 asyncHttpClient ,但现在这对我来说是一个障碍。我唯一的选择是确保服务器证书在我的密钥库中。该调用仍会启动 SSL 握手,然后失败。我使用 Postman 生成的 okHttp 代码进行 SAME https 调用,它可以工作。去图!!!
【解决方案2】:

这是我的代码:

private Map<String, String> mParams;

public void sendata(View v) throws JSONException {
    username = (EditText) findViewById(R.id.txtusername);
    password = (EditText) findViewById(R.id.txtpassword);

    final ProgressDialog pDialog = new ProgressDialog(this);
    pDialog.setMessage("Loading...");
    pDialog.show();
    JSONObject j = new JSONObject();
    j.put("password", password.getText());
    j.put("username", username.getText());
    j.put("Deviceid", 123456789);
    j.put("RoleId", 1);
    String url = Url;
    AsyncHttpClient client = new AsyncHttpClient();
    RequestParams params = new RequestParams();
    params.put("json", j.toString());
    client.post(url, params, new JsonHttpResponseHandler() {
        @SuppressLint("NewApi")
        public void onSuccess(JSONObject response) {
            pDialog.hide();
            JSONObject jsnObjct;
            try {
                JSONObject json = (JSONObject) new JSONTokener(response
                        .toString()).nextValue();
                JSONObject json2 = json.getJSONObject("Data");
                JSONArray test = (JSONArray) json2
                        .getJSONArray("PatientAllergies");
                for (int i = 0; i < test.length(); i++) {
                    json = test.getJSONObject(i);
                    System.out.print(json.getString("PatientId"));
                    System.out.print(json.getString("Id"));
                    System.out.print(json.getString("AllergyName"));
                    System.out.print(json.getString("Reaction"));
                    System.out.print(json.getString("OnSetDate"));
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        public void onFailure(int statusCode, Header[] headers, String res,
                Throwable t) {
            pDialog.hide();
        }
    });

}
JSONObject jsonObject;

private void parsejson(JSONObject response) {

    try {
        jsonObject = response;
        System.out.print(response.toString());
        JSONObject jsnObjct = jsonObject.getJSONObject("Data");
        System.out.print(jsonObject.toString());
        jsnObjct = jsnObjct.getJSONObject("PhysicianDetail");

        System.out.print(jsnObjct.toString());

    } catch (JSONException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}

【讨论】:

    【解决方案3】:

    您需要将公共服务器证书导入您的默认密钥库,或者如果您对客户端的身份验证不感兴趣,您可以使用

    初始化 AsyncHttpClient
    AsyncHttpClient asycnHttpClient = new AsyncHttpClient(true, 80, 443);
    

    但是这个技巧并不安全,因为使用了一个自定义的SSLSocketFactory 实现而忽略了 SSL 证书验证,请查看AsyncHttpClient 源代码。

    有关 SSLSocketFactory 的更多信息,请访问https://developer.android.com/reference/org/apache/http/conn/ssl/SSLSocketFactory.html

    【讨论】:

    【解决方案4】:

    我有一个调用 https 服务的简单 http 客户端:

    import android.util.Log;
    import org.apache.http.HttpResponse;
    import org.apache.http.NameValuePair;
    import org.apache.http.auth.AuthScope;
    import org.apache.http.auth.UsernamePasswordCredentials;
    import org.apache.http.client.HttpClient;
    import org.apache.http.client.ResponseHandler;
    import org.apache.http.client.entity.UrlEncodedFormEntity;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.impl.client.AbstractHttpClient;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.http.protocol.HTTP;
    
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.URL;
    import java.util.List;
    
    /**
     */
    public class HttpSimpleClient {
    
        private static final String TAG = HttpSimpleClient.class.getSimpleName();
    
        private static HttpSimpleClient instance;
    
        private HttpSimpleClient(){}
    
        public static HttpSimpleClient instance(){
            if (instance==null) {
                instance = new HttpSimpleClient();
            }
            return instance;
        }
    
        public <T> T post(URL url,
                          List<NameValuePair> header,
                          List<NameValuePair> parameter,
                          ResponseHandler<T> responseHandler) throws IOException {
            return post(url, header, parameter, responseHandler, null, null);
        }
    
        public <T> T post(URL url,
                         List<NameValuePair> header,
                         List<NameValuePair> parameter,
                         ResponseHandler<T> responseHandler,
                         AuthScope proxy,
                         UsernamePasswordCredentials proxyUser) throws IOException {
            HttpClient httpClient = new DefaultHttpClient();
            HttpPost request = new HttpPost(url.toString());
    
            if (header!=null) {
                for (NameValuePair head : header){
                    request.setHeader(head.getName(), head.getValue());
                }
                Log.d(TAG, "Aggiunti header: "+ header.size());
    
            } else {
                // Header di default
                request.setHeader("Content-Type", "application/x-www-form-urlencoded");
                request.setHeader("User-Agent", System.getProperty("http.agent"));
                Log.d(TAG, "Aggiunti header di defautl");
            }
    
            if (parameter!=null) {
                request.setEntity(new UrlEncodedFormEntity(parameter, HTTP.UTF_8));
                Log.d(TAG, "Aggiunti parametri: "+ parameter.size());
            }
    
    
            if (proxy!=null) {
                if (proxyUser!=null) {
                    ((AbstractHttpClient) httpClient).getCredentialsProvider().setCredentials(proxy, proxyUser);
    
                } else {
                    // TODO gestire proxy senza credenziali
                    ((AbstractHttpClient) httpClient).getCredentialsProvider().setCredentials(proxy, null);
    
                }
                Log.d(TAG, "Impostato Proxy per la connessione");
            }
            return httpClient.execute(request, responseHandler);
        }
    
    
        public static String httpResponseToString(HttpResponse httpResponse, int bufferSize) throws IOException {
            InputStream content = httpResponse.getEntity().getContent();
    
            int numRead;
            byte[] buffer = new byte[bufferSize];
            ByteArrayOutputStream outString = new ByteArrayOutputStream();
            try{
                while ((numRead = content.read(buffer)) != -1) {
                    outString.write(buffer, 0, numRead);
                }
            } finally {
                content.close();
            }
            return new String(outString.toByteArray());
        }
    }
    

    我在 AsyncTask 中使用它:

    response = HttpSimpleClient.instance().post(
                        getServiceURL(), // HTTPS url
                        mHeader, // List<NameValuePair>
                        mParameter, // List<NameValuePair>
                        getResponseHandler() // org.apache.http.client.ResponseHandler
                );
    

    在 Android api 上测试>=10

    【讨论】:

    • 我必须使用GET方法!!
    • HttpGet 请求 = new HttpGet(url.toString()); //带有参数而不是HttpPost的url
    猜你喜欢
    • 2017-08-05
    • 2017-08-31
    • 2016-03-05
    • 1970-01-01
    • 2015-04-01
    • 2014-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多