android sdk level 23中SSLParameter.setServerNames的替代方法是什么?

时间:2016-07-31 10:07:33

标签: android ssl sni

我正在使用SSLSocket连接到服务器。我想使用ssl SNI扩展。我可以在java中使用SSLParameter.setServerNames。但它出现在android中直到sdk 24才可用。这里有什么选择?

1 个答案:

答案 0 :(得分:0)

我有同样的问题,通过使用反射解决。 使用以下方法连接插座:

SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket socket = (SSLSocket) sf.createSocket(uri.getHost(), 443);
setSNIHost(sf, socket, uri.getHost());
SSLSession s = socket.getSession();

其中setSNIHost声明为:

public void setSNIHost(final SSLSocketFactory factory, final SSLSocket socket, final String hostname) {
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
        Log.i(TAG, "Setting SNI via SSLParameters");
        SNIHostName sniHostName = new SNIHostName(hostname);
        SSLParameters sslParameters = socket.getSSLParameters();
        List<SNIServerName> sniHostNameList = new ArrayList<>(1);
        sniHostNameList.add(sniHostName);
        sslParameters.setServerNames(sniHostNameList);
        socket.setSSLParameters(sslParameters);
    } else if (factory instanceof android.net.SSLCertificateSocketFactory) {
        Log.i(TAG, "Setting SNI via SSLCertificateSocketFactory");
        ((android.net.SSLCertificateSocketFactory)factory).setHostname(socket, hostname);
    } else {
        Log.i(TAG, "Setting SNI via reflection");
        try {
            socket.getClass().getMethod("setHostname", String.class).invoke(socket, hostname);
        } catch (Throwable e) {
            Log.e(TAG, "Could not call SSLSocket#setHostname(String) method ", e);
        }
    }
}

我真的不记得我在哪里复制了反射代码,我只是添加了对API 24的支持。