从OpenSSLSocketImpl派生的Android自定义套接字(非SSLSocket)
对不起,这是一个很长的问题,但有点牵扯其中。谢谢你的阅读 我有一个定制的套接字工厂和套接字类(Android5.0),我开发了它来执行我在该级别需要执行的一些特定任务。下面是我的套接字工厂和套接字(为了简单起见,我省略了许多方法): 我是这样使用这个工厂的:从OpenSSLSocketImpl派生的Android自定义套接字(非SSLSocket),android,sockets,Android,Sockets,对不起,这是一个很长的问题,但有点牵扯其中。谢谢你的阅读 我有一个定制的套接字工厂和套接字类(Android5.0),我开发了它来执行我在该级别需要执行的一些特定任务。下面是我的套接字工厂和套接字(为了简单起见,我省略了许多方法): 我是这样使用这个工厂的: private void doCustomSocketFactoryWithHttpUrlConnection() { try { String uri = "https://alice.sni.velox.c
private void doCustomSocketFactoryWithHttpUrlConnection() {
try {
String uri = "https://alice.sni.velox.ch";
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, null, null);
CustomSocketFactory customSocketFactory = new CustomSocketFactory(context.getSocketFactory());
HttpsURLConnection.setDefaultSSLSocketFactory(customSocketFactory);
URL url = new URL(uri);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
Log.d(TAG, "HTTP Response Code: " + conn.getResponseCode());
} catch (Exception e) {
Log.d(TAG, e.getLocalizedMessage());
}
}
这就像预期的一样,除非我访问了一个使用like的站点。在这种情况下,网站抱怨(我向Wireshark确认)我的应用程序没有发送SNI TLS头
取出我的自定义套接字工厂,并发送标头
进一步挖掘,我在Platform.java类中发现了这段代码(在HttpsURLConnection中使用了okhttp类)
openSSLSocketClass的设置方式如下:
Class<?> openSslSocketClass = Class.forName("com.android.org.conscrypt.OpenSSLSocketImpl");
Class openSslSocketClass=Class.forName(“com.android.org.conscrypt.OpenSSLSocketImpl”);
因此,此代码启用SNI和会话票证,但仅当套接字扩展OpenSSLSocketImpl时才启用
回到我的自定义套接字,在调试器中,我看到传递给构造函数的套接字类是:com.android.org.conscrypt.OpenSSLSocketImplWrapper(它扩展了OpenSSLSocketImpl)
因此,我错过了SNI和会话票证功能,因为我的套接字扩展了java.net.ssl.SSLSocket(而不是OpenSSLSocketImpl)
想到的最好的解决方案是让我的CustomSocket扩展OpenSSLSocketImpl并添加所需的委托方法,但我不知道如何导入OpenSSLSocketImpl。它似乎不在标准Android库中。Android文档只讨论了SSLSocket,没有提到OpenSSLSocketImpl
有没有一种方法可以让我的CustomSocket类从我缺少的OpenSSLSocketImpl进行扩展
我意识到我可以使用反射在CustomSocket类中的“委托”上调用这些方法,但我担心在所有情况下的可靠性以及在何处/何时进行这些调用。此外,如果他们继续使用类似的方法在新的Android版本中向OpenSSLSocketImpl类添加新功能,我也会错过这些功能
感谢您一路阅读 也许我对你没什么用处,但你可以尝试设置一个不同的客户端,比如jersey的客户端或apache http客户端,特别是因为Android自己的http客户端太旧了,应该更换 这取决于您需要在CustomSocket中实现什么功能,但您可以执行以下操作:
- 使CustomSocket扩展套接字(无SSL)
- 在套接字工厂中,创建一个普通的自定义套接字,然后使用
delegate.createSocket(s、主机、端口、自动关闭)
- 返回委托的结果,它的类型为
com.android.org.conscrypt.OpenSSLSocketImplWrapper
@Override public void enableTlsExtensions(SSLSocket socket, String uriHost) {
super.enableTlsExtensions(socket, uriHost);
if (!openSslSocketClass.isInstance(socket)) return;
try {
setUseSessionTickets.invoke(socket, true);
setHostname.invoke(socket, uriHost);
} catch (InvocationTargetException e) {
// snip
}
Class<?> openSslSocketClass = Class.forName("com.android.org.conscrypt.OpenSSLSocketImpl");