How to get 401 response without handling it using try/catch in android

做~自己de王妃 提交于 2019-12-03 12:30:02

问题


I am using HttpUrlConnection to make network requests from my android application. Everything works fine except one thing, 401. Whenever the server returns response with status code 401, my app throws IOException with a message stating, "no authentication challenge found". After googling it, I haven't found a single solution, but only workaround (handling it using try/catch, assuming its a 401 response).

here is the code snippet:

public Bundle request(String action, Bundle params, String cookie) throws FileNotFoundException, MalformedURLException, SocketTimeoutException,
        IOException {

    OutputStream os;

    String url = baseUrl + action;
    Log.d(TAG, url);
    HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
    conn.setConnectTimeout(30 * 1000);
    conn.setReadTimeout(30 * 1000);
    conn.setRequestProperty("User-Agent", System.getProperties().getProperty("http.agent") + "AndroidNative");
    conn.setRequestMethod("POST");
    conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
    conn.setRequestProperty("Connection", "Keep-Alive");
    conn.setDoOutput(true);
    conn.setDoInput(true);
    if (cookie != null) {
        conn.setRequestProperty("Cookie", cookie);
    }

    if (params != null) {
        os = conn.getOutputStream();
        os.write(("--" + boundary + endLine).getBytes());
        os.write((encodePostBody(params, boundary)).getBytes());
        os.write((endLine + "--" + boundary + endLine).getBytes());
        uploadFile(params, os);
        os.flush();
        os.close();
    }

    conn.connect();

    Bundle response = new Bundle();
    try {
        response.putInt("response_code", conn.getResponseCode());
        Log.d(TAG, conn.getResponseCode() + "");
        response.putString("json_response", read(conn.getInputStream()));
        List<String> responseCookie = conn.getHeaderFields().get("set-cookie");
        // Log.d(TAG, responseCookie.get(responseCookie.size() - 1));
        response.putString("cookie", responseCookie.get(responseCookie.size() - 1));
    } catch (SocketTimeoutException e) {
        throw new SocketTimeoutException(e.getLocalizedMessage());
    } catch (FileNotFoundException e) {
        throw new FileNotFoundException(e.getLocalizedMessage());
    } catch (IOException e) {
        e.printStackTrace();
        response.putInt("response_code", HttpURLConnection.HTTP_UNAUTHORIZED);
        response.putString("json_response", read(conn.getErrorStream()));
    }

    // debug
    Map<String, List<String>> map = conn.getHeaderFields();
    for (String key : map.keySet()) {
        List<String> values = map.get(key);
        for (String value : values) {
            Log.d(key, value);
        }
    }

    conn.disconnect();

    return response;
}

I really want to know, why this exception is thrown? What does authentication challenge mean? How to provide authentication challenge? what change I have to make in my code to overcome this situation?

Please enlighten me.. :)


回答1:


IOException is quite a general exception, and you cannot safely assume a 401 status code every time it's thrown.

If the first time you request the status code it happens to contain a 401, HttpURLConnection will throw an IOException. At this point, the internal status of the connection will have changed, and it will now be able to give you the status code, without any error.

int status = 0;
try {
    status = conn.getResponseCode();
} catch (IOException e) {
    // HttpUrlConnection will throw an IOException if any 4XX
    // response is sent. If we request the status again, this
    // time the internal status will be properly set, and we'll be
    // able to retrieve it.
    status = conn.getResponseCode();
}
if (status == 401) {
    // ...
}

For more details, http://www.tbray.org/ongoing/When/201x/2012/01/17/HttpURLConnection




回答2:


try to use HttpClient

private void setCredentials(String login, String password) {
    if (login != null && password != null)
        httpClient.getCredentialsProvider().setCredentials(
                new AuthScope(URL_HOST, 80), new UsernamePasswordCredentials(login, password));

}



private InputStream execute(String url, String login, String password) {
        setCredentials(login, password);
        HttpGet get = new HttpGet(url);
        try {
            HttpResponse response = httpClient.execute(get);
            int code = response.getStatusLine().getStatusCode();
            if (code == HttpURLConnection.HTTP_OK) {
                InputStream stream = response.getEntity().getContent();
                return stream;
            } else {
                Log.e("TAG", "Wrong response code " + code + " for request " + get.getRequestLine().toString());
                return null;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }


来源:https://stackoverflow.com/questions/11735636/how-to-get-401-response-without-handling-it-using-try-catch-in-android

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!