응용 프로그램이 서버와 통신 할 때 우리는 인증서 (공개 키 고정) (MITMA에 대한 추가 검사)를 작성했습니다. 서버와 통신하려면 HttpClient를 사용하십시오. 또한 프로덕션 환경에 프록시 서버가 있으므로 SNI를 사용해야합니다. 앱을 프로덕션에 게시하기 전에 다른 환경 (TEST 환경)에서 확인합니다. TEST env에는 자체 서명 된 인증서 만 있으므로 테스트 용으로 만 사용되므로이 경우에만 새 인증서를 구입하고 싶지는 않습니다.사용자 정의 SSLSocketFactory는 사용자 정의 신뢰 관리자를 사용하지 않습니다.
구현하려면 맞춤 SSLSocketFactory (org.apache.http.conn.ssl.SSLSocketFactory)를 만들었습니다. 그러나 자체 서명 된 인증서에는 문제가 없습니다. 사용자 지정 trustManager (IgnoreCertificatesTrustManager)를 sslSocketFactory (SSLCertificateSocketFactory)로 설정합니다. 나는 다음과 같은 코드를 사용하는 경우 :
SSLContext sslContext = SSLContext.getInstance(SSLSocketFactory.TLS);
sslContext.init(null, new TrustManager[] { new IgnoreCertificatesTrustManager() }, null);
sslSocket = (SSLSocket) sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
자기 불똥이 튄 인증서 작품의 검사 (의 TrustManager (IgnoreCertificatesTrustManager)의 체크를 무시를). 그러나이 코드는 SNI 솔루션을 지원하지 않습니다. 내가 뭘 잘못 했니?
감사합니다.
private class CustomSSLSocketFactory extends SSLSocketFactory {
public CustomSSLSocketFactory() throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException, CertificateException {
super(null);
}
// Plain TCP/IP (layer below TLS)
@Override
public Socket connectSocket(Socket s, String host, int port, InetAddress localAddress, int localPort, HttpParams params) throws IOException {
return null;
}
@Override
public Socket createSocket() throws IOException {
return null;
}
@Override
public boolean isSecure(Socket s) throws IllegalArgumentException {
if (s instanceof SSLSocket) {
return ((SSLSocket) s).isConnected();
}
return false;
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
@Override
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
SSLSocket sslSocket = null;
// if (isProduction()) {
if (autoClose) {
// we don't need the plainSocket
socket.close();
}
// create and connect SSL socket, but don't do hostname/certificate verification yet
SSLCertificateSocketFactory sslSocketFactory = (SSLCertificateSocketFactory) SSLCertificateSocketFactory.getDefault(0, null);
// NOT works!
sslSocketFactory.setTrustManagers(new TrustManager[] { new IgnoreCertificatesTrustManager() });
// ----
sslSocket = (SSLSocket) sslSocketFactory.createSocket(socket, host, port, autoClose);
// enable TLSv1.1/1.2 if available (see https://github.com/rfc2822/davdroid/issues/229)
sslSocket.setEnabledProtocols(sslSocket.getSupportedProtocols());
// set up SNI before the handshake
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
logger.debug("Setting SNI hostname");
sslSocketFactory.setHostname(sslSocket, host);
} else {
logger.debug("No documented SNI support on Android <4.2, trying with reflection");
try {
java.lang.reflect.Method setHostnameMethod = sslSocket.getClass().getMethod("setHostname", String.class);
setHostnameMethod.invoke(sslSocket, host);
} catch (Exception e) {
logger.error("SNI not useable", e);
}
}
// } else {
// try {
// SSLContext sslContext = SSLContext.getInstance(SSLSocketFactory.TLS);
// sslContext.init(null, new TrustManager[] { new IgnoreCertificatesTrustManager() }, null);
// sslSocket = (SSLSocket) sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
// } catch (java.security.NoSuchAlgorithmException e) {
// throw new IOException(e);
// } catch (KeyManagementException e) {
// throw new IOException(e);
// }
// }
// verify certificate
SSLSession session = sslSocket.getSession();
X509Certificate[] certificates = (X509Certificate[]) session.getPeerCertificates();
if (!checkPublicKey(certificates)) {
throw new IOException("SSL_HANDSHAKE_FAILED");
}
return sslSocket;
}
}
아무 것도 필요하지 않습니다. 트러스트 매니저로'SSLContext'를 초기화하십시오. isSecure()의 이상한 정의.'isConnected()는 그것과 무엇을 관계가 있는가? – EJP
SNI를 지원하는 HTTPClient 버전을 사용하고 있습니까? 일반적으로 Android는 SNI를 지원하지 않는 Apache HTTPClient의 이전 버전과 함께 제공됩니다. –
동일한'SSLContext'에서 * 자체 서명 된 인증서와 일반적인 CA 기반의 인증서를 모두 지원하려면 부울 논리를 수행 할 수있는 적절한 'TrustManager'를 만들어야합니다. 내 [CWAC-Security 라이브러리] (https://github.com/commonsguy/cwac-security/)의 'TrustManagerBuilder'를 참조하십시오. – CommonsWare