【问题标题】:AsyncTask HttpsUrlConnection throw IOException on getOutputStream()AsyncTask HttpsUrlConnection 在 getOutputStream() 上抛出 IOException
【发布时间】:2016-04-18 14:43:32
【问题描述】:

我尝试使用包含 json 数据(用户名和密码)的 POST 请求登录到 Web 服务器 REST API。问题是当我调用 urlConnection.getOutputStream() 时会抛出 IOException。

我尝试在 urlConnection.getOutputStream() 之前调用 urlConnection.setDoOutput(true)urlConnection.setDoInput(true) 但直到同样的错误。但是当我尝试使用 GET 方法从 google.com 之类的网站读取数据时,没有错误。

一种可能是使用 HttpClient,但该库已被弃用。

e.printStackTrace() 什么也不打印。

网络服务器的证书是自签名的。 要执行此操作,我使用 AsyncTask。 安卓版本 4.1.2 安卓工作室 1.3 RC3 minSdkVersion 11 targetSdkVersion 23

是因为自签名证书吗? 有人可以帮我吗?

@Override
protected Void doInBackground(Void... params) {
    login();
    return null;
}


private KeyStore getKeyStore() {
    KeyStore trusted;
    try {
        trusted = KeyStore.getInstance("BKS");
        InputStream in = activity.getBaseContext().getResources().openRawResource(R.raw.cert);
        try {
            trusted.load(in, "password".toCharArray());
        } finally {
            in.close();
        }
    } catch (Exception e) {
        throw new AssertionError(e);
    }

    return trusted;
}

public void login() {
    HttpsURLConnection urlConnection = null;
    try {
        //prepare request
        URL url = new URL("https://" + ip + "/api/login");

        urlConnection = (HttpsURLConnection) url.openConnection();

        TrustManagerFactory tmf = null;
        SSLContext context;
        try {
            tmf = TrustManagerFactory.getInstance("X509");
            tmf.init(getKeyStore());
            context = SSLContext.getInstance("TLS");
            context.init(null, tmf.getTrustManagers(), null);

            urlConnection.setSSLSocketFactory(context.getSocketFactory());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }  catch (KeyManagementException e) {
            e.printStackTrace();
        }

        urlConnection.setRequestMethod("POST");
        urlConnection.addRequestProperty("Content-Type", "application/json");

        //write request
        urlConnection.setDoOutput(true);
        urlConnection.setChunkedStreamingMode(0);

        //error at this line
        OutputStreamWriter out = new OutputStreamWriter(urlConnection.getOutputStream());

        String logginRequest = "{'login' : '" + login + "', 'password' : '" + password + "'}";
        out.write(logginRequest.toCharArray());
        out.close()

        //connect
        urlConnection.connect();

        //read
        BufferedInputStream in = new BufferedInputStream(urlConnection.getInputStream());
        printData(in);
        in.close();
    } catch (MalformedURLException e) {
        Log.e("ConcentratorExport", "MalformedURLException");
        e.printStackTrace();
    } catch (IOException e) {
        Log.e("ConcentratorExport", "IOException");
        e.printStackTrace();
    } finally {
        urlConnection.disconnect();
    }
}

应用权限:

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />

【问题讨论】:

  • 哪个 IOException?使用 e.getMessage()。改为 Log.e("ConcentratorExport", "IOException:" + e.getMessage());
  • 把这样的日志语句放在每个catch块中。
  • 捕获后不要继续代码而是返回。
  • 你可以在stackoverflow.com/questions/34540584/… 看到我对 sslsocketfactory & hostnameverifier 的回答

标签: java android http io httpurlconnection


【解决方案1】:

我找到了答案。 Log.e("ConcentratorExport", e.getMessage()) 显示的错误消息是 Hostname '160.98.21.182' was not verified

之后,我写了一个类来接受所有主机名,见java.io.IOException: Hostname was not verified,并将其设置为默认主机名验证器: HttpsURLConnection.setDefaultHostnameVerifier(new IPSHostnameVerrifier()) 并且成功了。

另一个错误是json字符串必须使用“而不是':

String logginRequest = "{\"login\" : \"" + login + "\", \"password\" : \"" + password + "\"}";

【讨论】:

    猜你喜欢
    • 2014-06-28
    • 2014-04-18
    • 1970-01-01
    • 2020-07-24
    • 1970-01-01
    • 2012-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多