【问题标题】:Android, HttpURLConnection and handling bad credentialsAndroid、HttpURLConnection 和处理错误凭据
【发布时间】:2011-10-27 00:49:44
【问题描述】:

我正在执行一个 GET 请求:

HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
urlConnection.setConnectTimeout(CONNECT_TIMEOUT);
urlConnection.setReadTimeout(READ_TIMEOUT);
urlConnection.connect();

凭证已设置的时间:

Authenticator.setDefault(new Authenticator() {
  protected PasswordAuthentication getPasswordAuthentication() {
     return new PasswordAuthentication(loginNameString, passwordString.toCharArray());
  }
});

当我提供良好的凭据(即用户名和密码)时,一切正常。

提供错误凭据时,连接会发生什么情况?例如,如果我故意提供错误的凭据,并且在urlConnection.connect() 之后立即调用urlConnection.getResponseCode(),我的应用程序最终会超时,我必须强制关闭。这是为什么呢?

** 编辑。据我所知,当凭据错误时,HttpURLConnection 只是继续尝试连接(即使超时时间有限)。 (我知道这一点是因为我在返回之前在我的getPasswordAuthentication() 方法中添加了Log.v("Authentication", "Calling..."); 行)。如果凭据错误导致连接失败,我希望连接停止尝试!

【问题讨论】:

    标签: android httpurlconnection


    【解决方案1】:

    您可以在第一次错误身份验证后使用标志并在身份验证器中返回 null 来解决此问题。

    通过这种方式,您的InputStream 将引发一个您可以在之后处理的异常。

    复制自:https://stackoverflow.com/a/13615011/628713:

    public class MyRequest
    {
        private boolean alreadyTriedAuthenticating = false;
        private URL url;
    
        ...
    
        public void send()
        {
            HttpUrlConnection connection = (HttpUrlConnection) url.openConnection();
            Authenticator.setDefault(new Authenticator() {
                protected PasswordAuthentication getPasswordAuthentication() {
                    if (!alreadyTriedAuthenticating)
                    {
                        alreadyTriedAuthenticating = true;
                        return new PasswordAuthentication(username, password.toCharArray());
                    }
                    else
                    {
                        return null;
                    }
                }
                InputStream in = new BufferedInputStream(connection.getInputStream());
    
                ...
    
        }
    }
    

    【讨论】:

      【解决方案2】:

      我发现在 2.3.7 上设置 Authorization 标头会导致 400 响应代码,所以这里是一个经过调整的 Authenticator:

      public class FixedAuthenticator extends Authenticator {
      
          private PasswordAuthentication passAuth;
      
          public FixedAuthenticator(PasswordAuthentication passAuth) {
              this.passAuth = passAuth;
          }
      
          @Override
          protected PasswordAuthentication getPasswordAuthentication() {
              try {
                  return passAuth;
              } finally {
                  passAuth = null;
              }
          }
      }
      

      您需要在连接之前设置它的新实例:

      ...
      Authenticator.setDefault(new FixedAuthenticator(passAuth));
      connection.connect();
      

      A working example.

      【讨论】:

        【解决方案3】:

        使用基本身份验证,解决方法是:

        connection.setRequestProperty("Authorization", "Basic " + Base64.encodeToString((username + ":" + password).getBytes(), Base64.DEFAULT));
        

        使用android.util.Base64 包。另请注意,encodeToString() 方法自 API 8 (Android 2.2) 起可用。

        另外,http://code.google.com/p/android/issues/detail?id=7058 是相关的。

        【讨论】:

        • 谢谢! aosp 中的错误 7058 正是它 - 我们应该要求用户提供一组新的凭据,因为他们以前的凭据失败了。
        猜你喜欢
        • 2018-09-19
        • 2014-09-12
        • 2019-12-02
        • 1970-01-01
        • 2015-12-04
        • 2020-03-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多