簡體   English   中英

AsyncTask HttpsUrlConnection在getOutputStream()上拋出IOException

[英]AsyncTask HttpsUrlConnection throw IOException on getOutputStream()

我嘗試使用包含json數據(用戶名和密碼)的POST請求登錄Web服務器REST API。 問題是當我調用urlConnection.getOutputStream()時 ,拋出IOException。

試圖在 urlConnection.getOutputStream()之前調用urlConnection.setDoOutput(true)urlConnection.setDoInput(true ),但是直到出現相同的錯誤。 但是,當我嘗試使用GET方法從類似google.com的網站讀取數據時,沒有任何錯誤。

一種可能性是使用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" />

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

之后,我編寫了一個類來接受所有主機名,請參見java.io.IOException:主機名未驗證 ,並將其設置為默認主機名驗證程序: HttpsURLConnection.setDefaultHostnameVerifier(new IPSHostnameVerrifier()) ,它可以正常工作。

另一個錯誤是json字符串必須使用“而不是':

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM