Java 带netty服务器的Android客户端(SSLSocket)
我创建了一个非常简单的Netty安全聊天服务器,如本教程所述,并从以下内容开始:Java 带netty服务器的Android客户端(SSLSocket),java,android,ssl,netty,Java,Android,Ssl,Netty,我创建了一个非常简单的Netty安全聊天服务器,如本教程所述,并从以下内容开始: SelfSignedCertificate ssc = new SelfSignedCertificate(); SslContext sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());` 之后,我创建了一个简单的SSLSocket,以便通过Android手机与之通信。我通过另一个线程执行连接,并按照以下方式进行配
SelfSignedCertificate ssc = new SelfSignedCertificate();
SslContext sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());`
之后,我创建了一个简单的SSLSocket,以便通过Android手机与之通信。我通过另一个线程执行连接,并按照以下方式进行配置:
protected SSLSocket getConnection(String ip, int port) throws IOException {
try {
KeyStore trustStore = KeyStore.getInstance("BKS");
InputStream trustStoreStream = context.getResources().openRawResource(R.raw.server);
trustStore.load(trustStoreStream, "myPassword".toCharArray());
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(trustStore);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
SSLSocketFactory factory = sslContext.getSocketFactory();
SSLSocket socket = (SSLSocket) factory.createSocket(ip, port);
socket.setEnabledCipherSuites(SSLUtils.getCipherSuitesWhiteList(socket.getEnabledCipherSuites()));
return socket;
} catch (GeneralSecurityException e) {
throw new IOException(e.getMessage());
}
}
那样的话,我会做一个
sslsocket = getConnection(SERVERIP, SERVERPORT);
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(sslsocket.getOutputStream())));
在“out=…”这一行,会引发以下异常:
01-12 14:43:16.002:W/System.err(9979):javax.net.ssl.SSLHandshakeException:?java.security.cert.CertPathValidatorException:找不到证书路径的信任锚点。
01-12 14:43:16.002:W/System.err(9979):位于com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:409)
01-12 14:43:16.012:W/System.err(9979):在com.android.org.conscrypt.OpenSSLSocketImpl$SSLOutputStream。(OpenSSLSocketImpl.java:706)
01-12 14:43:16.012:W/System.err(9979):位于com.android.org.conscrypt.OpenSSLSocketImpl.getOutputStream(OpenSSLSocketImpl.java:643)
01-12 14:43:16.012:W/System.err(9979):位于com.mypath.connector.TCPClient.run(TCPClient.java:106)
01-12 14:43:16.012:W/System.err(9979):位于com.mypath.SplashActivity$connectTask.doInBackground(SplashActivity.java:48)
01-12 14:43:16.012:W/System.err(9979):位于com.mypath.SplashActivity$connectTask.doInBackground(SplashActivity.java:1)
01-12 14:43:16.012:W/System.err(9979):在android.os.AsyncTask$2.call(AsyncTask.java:288)
01-12 14:43:16.012:W/System.err(9979):位于java.util.concurrent.FutureTask.run(FutureTask.java:237)
01-12 14:43:16.012:W/System.err(9979):在android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
01-12 14:43:16.012:W/System.err(9979):位于java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
01-12 14:43:16.012:W/System.err(9979):位于java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
01-12 14:43:16.012:W/System.err(9979):位于java.lang.Thread.run(Thread.java:841)
01-12 14:43:16.012:W/System.err(9979):原因:java.security.cert.CertificateException:java.security.cert.CertPathValidator异常:找不到证书路径的信任锚。
01-12 14:43:16.012:W/System.err(9979):位于com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:282)
01-12 14:43:16.012:W/System.err(9979):位于com.android.org.conscrypt.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:202)
01-12 14:43:16.012:W/System.err(9979):位于com.android.org.conscrypt.OpenSSLSocketImpl.verifyCertificateCain(OpenSSLSocketImpl.java:611)
01-12 14:43:16.012:W/System.err(9979):在com.android.org.conscrypt.NativeCrypto.SSL_do_握手(本机方法)
01-12 14:43:16.012:W/System.err(9979):位于com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:405)
01-12 14:43:16.012:W/系统错误(9979):。。。还有11个
01-12 14:43:16.012:W/System.err(9979):原因:java.security.cert.CertPathValidator异常:找不到证书路径的信任锚。
01-12 14:43:16.012:W/系统错误(9979):。。。还有16个
有人知道我做错了什么吗?出于开发目的,您可以使用对所有人的信任
TrustManager
。这种“解决方案”根本不安全。
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;
}
};
最佳解决方案是:
您的客户端应该信任服务器证书,因此为了测试目的,您可以使用Netty的不安全的TrustManagerFactory,而不是使用JAVA的TrustManagerFactory并对其进行配置(这有时很繁琐)。这样,您的客户端将信任服务器发送的任何证书。但一定不要在生产中使用,这是非常不安全的