【问题标题】:ignore ssl errors in DefaultHttpClient忽略 DefaultHttpClient 中的 ssl 错误
【发布时间】:2011-08-29 12:14:08
【问题描述】:

我正在寻找忽略默认 httpclient 中所有 ssl 错误(例如,不受信任)的可能性。我在这里看到了很多解决方案,但我总是必须导入一个特定的证书并将其添加到信任管理器,或者它是用于 DefaultHttpClient 的 HttpsUrlConnection 的。 我使用的网络请求是:

    public static String makeGETRequest(String s,String encoding)
{
    DefaultHttpClient http = new DefaultHttpClient();
    final String username = "USERNAME";
    final String password = "PASSWORD";
    UsernamePasswordCredentials c = new UsernamePasswordCredentials(username,password);
    BasicCredentialsProvider cP = new BasicCredentialsProvider(); 
    cP.setCredentials(AuthScope.ANY, c); 
    http.setCredentialsProvider(cP);
    HttpResponse res;
    try {

        res = http.execute(new HttpGet(s));
        InputStream is = res.getEntity().getContent();
        BufferedInputStream bis = new BufferedInputStream(is);
        ByteArrayBuffer baf = new ByteArrayBuffer(50);
        int current = 0;
        while((current = bis.read()) != -1){
              baf.append((byte)current);
         }

        return  new String(baf.toByteArray(),encoding);
       } 
    catch (ClientProtocolException e) {
        // TODO Auto-generated catch block
        return "error: " + e.getMessage();
    } 
    catch (IOException e) {
        // TODO Auto-generated catch block
        return "error: " + e.getMessage();
    } 

}

还有:

public static String makePOSTRequest(String s, List <NameValuePair> nvps,String encoding)
{
    DefaultHttpClient http = new DefaultHttpClient();
    final String username = "USERNAME";
    final String password = "PASSWORD";
    UsernamePasswordCredentials c = new UsernamePasswordCredentials(username,password);
    BasicCredentialsProvider cP = new BasicCredentialsProvider(); 
    cP.setCredentials(AuthScope.ANY, c); 
    http.setCredentialsProvider(cP);
    HttpResponse res;
    try {
        HttpPost httpost = new HttpPost(s);
        httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.DEFAULT_CONTENT_CHARSET));
        res = http.execute(httpost);
        InputStream is = res.getEntity().getContent();
        BufferedInputStream bis = new BufferedInputStream(is);
        ByteArrayBuffer baf = new ByteArrayBuffer(50);
        int current = 0;
        while((current = bis.read()) != -1){
              baf.append((byte)current);
         }
        res = null;
        httpost = null;
        String ret = new String(baf.toByteArray(),encoding);
        return  ret;
       } 
    catch (ClientProtocolException e) {
        // TODO Auto-generated catch block
        return e.getMessage();
    } 
    catch (IOException e) {
        // TODO Auto-generated catch block
        return e.getMessage();
    } 

}

有人知道如何忽略这段代码中的 ssl 错误吗?

编辑: 因为我必须只信任一个特定的(过期)证书,所以我尝试通过以下方式覆盖 DefaultHttpClient:

public class MyHttpClient extends DefaultHttpClient {
final Context context;

  public MyHttpClient(Context context) {
    this.context = context;
  }

  @Override protected ClientConnectionManager createClientConnectionManager() {
    SchemeRegistry registry = new SchemeRegistry();
    registry.register(
        new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
    registry.register(new Scheme("https", newSslSocketFactory(), 443));
    return new SingleClientConnManager(getParams(), registry);
  }

  private SSLSocketFactory newSslSocketFactory() {
    try {
      KeyStore trusted = KeyStore.getInstance("BKS");
      InputStream in = context.getResources().openRawResource(R.raw.mykeystore);
      try {
        trusted.load(in, "mypassword".toCharArray());
      } finally {
        in.close();
      }
      return new SSLSocketFactory(trusted);
    } catch (Exception e) {
      throw new AssertionError(e);
    }
  }

}

R.raw.mykeystore 中的文件是一个.bks 文件,我用Portecle 创建的,我创建了一个新的bks 并导入了过期证书的存储pem,它似乎可以工作并且没有加载keystored错误,但如果我执行请求,我会收到消息“没有对等证书”的 IO 异常,可能是什么问题?

【问题讨论】:

  • “忽略 SSL 错误(例如不受信任)”是不安全的。请参阅 RFC 2246。如果您不希望它安全,为什么要使用 SSL?
  • 感谢您转换为评论;)正如我所写,过期的 ssl 证书来自第三方代理,我告诉他们安装一个有效的,但我必须编写一个快速的解决方法来启用为我的客户提供功能,而证书已过期...
  • 根据 EJP 的评论,选择性地容忍过期的证书并让任何证书通过是非常不同的事情。

标签: android ssl


【解决方案1】:

我解决了这个问题。如果您使用上述请求,它会起作用,但不要使用 DefaultHttpClient,而是使用您自己的版本:

public class MyHttpClient extends DefaultHttpClient {
final Context context;
TrustManager easyTrustManager = new X509TrustManager() {
    @Override
    public void checkClientTrusted(
            X509Certificate[] chain,
            String authType) throws CertificateException {
    }

    @Override
    public void checkServerTrusted(
            X509Certificate[] chain,
            String authType) throws CertificateException {
    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return null;
    }    
};
  public MyHttpClient(Context context) {
    this.context = context;
  }

  @Override protected ClientConnectionManager createClientConnectionManager() {
    SchemeRegistry registry = new SchemeRegistry();
    registry.register(
        new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
    registry.register(new Scheme("https", newSslSocketFactory(), 443));
    return new SingleClientConnManager(getParams(), registry);
  }


  private MySSLSocketFactory newSslSocketFactory() {
    try {
      KeyStore trusted = KeyStore.getInstance("BKS");      
      try {
         trusted.load(null, null);

      } finally {
      }

      MySSLSocketFactory sslfactory =  new MySSLSocketFactory(trusted);
        sslfactory.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        return sslfactory;
    } catch (Exception e) {
      throw new AssertionError(e);
    }

  }
  public class MySSLSocketFactory extends SSLSocketFactory {
        SSLContext sslContext = SSLContext.getInstance("TLS");

        public MySSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
            super(truststore);

            TrustManager tm = new X509TrustManager() {
                public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                }

                public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                }

                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
            };

            sslContext.init(null, new TrustManager[] { tm }, null);
        }

        @Override
        public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
            return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
        }

        @Override
        public Socket createSocket() throws IOException {
            return sslContext.getSocketFactory().createSocket();
        }
    }
   }

【讨论】:

  • 此代码将在 os 2.2 版中产生一个损坏的管道错误,在 2.3.3 + 中修复
  • 未使用字段easyTrustManager!
猜你喜欢
  • 2011-02-14
  • 2012-05-10
  • 2014-07-30
  • 1970-01-01
  • 2011-10-19
  • 2019-04-06
  • 2015-04-22
  • 2016-08-28
  • 1970-01-01
相关资源
最近更新 更多