2011-08-29 4 views
2

기본 httpclient에서 모든 SSL 오류 (예 : 신뢰할 수 없음)를 무시할 수 있는지 검색합니다. 나는 여기에서 많은 솔루션을 보았지만, 나는 특정 인증서를 가져와야 만 trustmanager에 추가하거나 DefaultHttpClient의 HttpsUrlConnection instad를 가져야한다. 내 사용 webrequests은 다음과 같습니다DefaultHttpClient에서 ssl 오류를 무시합니다.

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는 Portecle으로 만든 .bks 파일입니다. 새 bks를 만들고 만료 된 인증서의 저장된 Pem을 가져 왔으며, 작동하고 키 저장소가 오류없이로드되었지만 요청을 수행하면 "예외 없음"메시지와 함께 IO 예외가 발생했습니다. 문제점이있을 수 있습니다.

+1

'SSL 오류 무시 (예 : 신뢰할 수 없음)'는 안전하지 않습니다. RFC 2246을 참조하십시오. SSL을 사용하지 않는 이유는 무엇입니까? – EJP

+0

주석으로 변환 주셔서 감사합니다;) 내가 쓴 것처럼, 만료 된 SSL 인증서는 타사 프록시에서, 나는 그들에게 유효한 하나를 설치하라고 명령하지만 내 고객을위한 기능을 사용하려면 빠른 해결 방법을 wirite해야합니다. 인증서가 만료되었습니다. – 2red13

+0

EJP의 의견에 따라, 만료 된 인증서를 선택적으로 허용하고 절대적으로 인증서를 통과시키는 것은 매우 다른 것입니다. – Bruno

답변

11

나는이 문제를 해결했다. 위 요청을 사용하는 경우 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(); 
     } 
    } 
    } 
+0

이 코드는 2.3.3 + – 2red13

+0

에서 수정 된 os 버전 2.2에서 깨진 파이프 오류를 피합니다. 사용하지 않는 필드 easyTrustManager! –

+0

이 코드는 나를 위해 일했습니다. 감사합니다. –

관련 문제