AsyncTask HttpsUrlConnection在getOutputStream()上抛出IOException

时间:2016-01-13 14:56:31

标签: java android http io httpurlconnection

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

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

一种可能性是使用HttpClient,但不推荐使用此库。

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

Web服务器的证书是自签名的。 要执行此操作,我使用AsyncTask。 Android版本4.1.2 Android studio 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" />

1 个答案:

答案 0 :(得分:0)

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

之后,我编写了一个接受所有主机名的类,请参阅java.io.IOException: Hostname was not verified,并将其设置为默认主机名验证程序: HttpsURLConnection.setDefaultHostnameVerifier(new IPSHostnameVerrifier())并且它有效。

另一个错误是&#34;必须使用而不是&#39;对于json字符串:

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