在TLS协商期间,客户端向服务器发送支持的密码列表,服务器选择一个,加密开始.当我使用HttpsURLConnection进行通信时,我想更改
Android发送到服务器的密码列表.
我知道我可以在HttpsURLConnection对象上使用setSSLSocketFactory来设置它来使用SSLSocketFactory.当我想要更改由SSLSocketFactory返回的SSLSocket使用的trustmanager等时,这很有用.
我知道一般来说,这个密码列表可以使用SSLParameters对象编辑,并使用它们提供的方法将其传递给SSlsocket或SSLEngine对象.
但是SSLSocketFactory似乎没有公开这样的方法!
我找不到一种方法来更改SSLSocketFactory创建的返回的SSLSocket对象的SSLParameters,我传递给HttpsURLConnection.
该怎么办?
我想这也是一般Java的关系,不仅Android.也许有一个OO的方法来做(例如扩展SSLSocketFactory并提供给HttpsURLConnection?)
解决方法
这段代码有点生气.请小心使用.
public class PreferredCipherSuiteSSLSocketFactory extends SSLSocketFactory { private static final String PREFERRED_CIPHER_SUITE = "TLS_RSA_WITH_AES_128_CBC_SHA"; private final SSLSocketFactory delegate; public PreferredCipherSuiteSSLSocketFactory(SSLSocketFactory delegate) { this.delegate = delegate; } @Override public String[] getDefaultCipherSuites() { return setupPreferredDefaultCipherSuites(this.delegate); } @Override public String[] getSupportedCipherSuites() { return setupPreferredSupportedCipherSuites(this.delegate); } @Override public Socket createSocket(String arg0,int arg1) throws IOException,UnknownHostException { Socket socket = this.delegate.createSocket(arg0,arg1); String[] cipherSuites = setupPreferredDefaultCipherSuites(delegate); ((SSLSocket)socket).setEnabledCipherSuites(cipherSuites); return socket; } @Override public Socket createSocket(InetAddress arg0,int arg1) throws IOException { Socket socket = this.delegate.createSocket(arg0,arg1); String[] cipherSuites = setupPreferredDefaultCipherSuites(delegate); ((SSLSocket)socket).setEnabledCipherSuites(cipherSuites); return socket; } @Override public Socket createSocket(Socket arg0,String arg1,int arg2,boolean arg3) throws IOException { Socket socket = this.delegate.createSocket(arg0,arg1,arg2,arg3); String[] cipherSuites = setupPreferredDefaultCipherSuites(delegate); ((SSLSocket)socket).setEnabledCipherSuites(cipherSuites); return socket; } @Override public Socket createSocket(String arg0,int arg1,InetAddress arg2,int arg3) throws IOException,arg3); String[] cipherSuites = setupPreferredDefaultCipherSuites(delegate); ((SSLSocket)socket).setEnabledCipherSuites(cipherSuites); return socket; } @Override public Socket createSocket(InetAddress arg0,int arg3) throws IOException { Socket socket = this.delegate.createSocket(arg0,arg3); String[] cipherSuites = setupPreferredDefaultCipherSuites(delegate); ((SSLSocket)socket).setEnabledCipherSuites(cipherSuites); return socket; } private static String[] setupPreferredDefaultCipherSuites(SSLSocketFactory sslSocketFactory) { String[] defaultCipherSuites = sslSocketFactory.getDefaultCipherSuites(); ArrayList<String> suitesList = new ArrayList<String>(Arrays.asList(defaultCipherSuites)); suitesList.remove(PREFERRED_CIPHER_SUITE); suitesList.add(0,PREFERRED_CIPHER_SUITE); return suitesList.toArray(new String[suitesList.size()]); } private static String[] setupPreferredSupportedCipherSuites(SSLSocketFactory sslSocketFactory) { String[] supportedCipherSuites = sslSocketFactory.getSupportedCipherSuites(); ArrayList<String> suitesList = new ArrayList<String>(Arrays.asList(supportedCipherSuites)); suitesList.remove(PREFERRED_CIPHER_SUITE); suitesList.add(0,PREFERRED_CIPHER_SUITE); return suitesList.toArray(new String[suitesList.size()]); } }
当你想使用它
HttpsURLConnection connection = (HttpsURLConnection) (new URL(url)) .openConnection(); SSLContext context = SSLContext.getInstance("TLS"); TrustManager tm[] = {new SSLPinningTrustManager()}; context.init(null,tm,null); SSLSocketFactory preferredCipherSuiteSSLSocketFactory = new PreferredCipherSuiteSSLSocketFactory(context.getSocketFactory()); connection.setSSLSocketFactory(preferredCipherSuiteSSLSocketFactory); connection.connect();
谢谢.