在TLS协商期间,客户端将支持的密码列表发送到服务器,服务器选择一个密码,然后开始加密.当我HttpsURLConnection
用于通信时,我想更改Android发送到服务器的密码列表.
我知道我可以setSSLSocketFactory
在HttpsURLConnection
对象上使用它来设置它SSLSocketFactory
.当我想要更改由SSLSocket
返回的信任管理器等时,这非常有用SSLSocketFactory
.
我知道一般这个密码组列表可以使用编辑SSLParameters
对象,并将其传递到SSlsocket
或SSLEngine
使用他们提供的方法的对象.
但SSLSocketFactory
似乎没有公开这样的方法!
我找不到一种方法来改变我传递给的创建SSLParameters
的返回SSLSocket
对象.SSLSocketFactory
HttpsURLConnection
该怎么办?
我想这也与Java有关,不仅仅是Android.也许有一种OO方式来做(例如扩展SSLSocketFactory
并提供给它HttpsURLConnection
?)
编辑:道歉,如果我的原始帖子措辞不好.它引起了一些混乱,以对原始帖子的评论为代表.那么让我再试一次:
我开始提问.我想在Android上解决问题,但不知道如何.我花了很多时间在网上寻找解决方案,但在任何地方都找不到关于此问题的单一讨论.尽管如此,包括StackOverflow线程在内的一些讨论让我看到了一种前景看好的技术.我解决了这个问题.但解决方案有点牵扯.所以我决定在这里发布这个问题,思考a)必须有一个更好的解决方案,并希望有人知道并在这里发布答案; 或者b)也许这是一个很好的解决方案,因为我发现网上其他任何地方都没有讨论过这个问题,也许我对这个问题的解决方案对于其他试图做同样事情的人来说也是有用的.无论哪种方式,结果都将是对StackOverflow的新贡献:一个在其他地方无法回答的问题,最终会以某种方式回答正确答案.实际上,StackOverflow甚至邀请我在我最初发布它时通过分享我的知识来回答我自己的问题.事实上,那是我动机的一部分.即使是这件事的事实也没有收集到我找到的任何地方.
所以:
问:当使用AndroidHttpClient通过HTTPS发出REST请求时,如何指定要使用的SSL协议和密码?
这个很重要.很明显,服务器上可以做很多事情,但是有限制.同一台服务器必须提供浏览器,包括旧浏览器以及其他客户端.这意味着服务器必须支持广泛的协议和密码.即使在Android中,如果你必须支持许多不同的版本,你将不得不支持许多不同的协议和密码.
更重要的是,默认情况下,OpenSSL 在SSL握手期间尊重客户端的密码首选项,而不是服务器的密码首选项.例如,请参阅此文章,其中说明您可以通过设置SSL_OP_CIPHER_SERVER_PREFERENCE来覆盖客户端中的该行为.目前还不完全清楚这个选项是否可以在Java中的SSLSocket上设置.即使可以,您也可以自己设置密码列表或告诉客户端尊重服务器列表.否则,您将获得Android默认值,无论您运行的版本是什么(不是您链接的版本).
如果采用默认值,可以在此处看到客户端从Jellybean 4.2+客户端发送到服务器的首选项列表,从第504行开始.默认的协议列表从第620行开始.虽然Jellybean 4.2+包含对OpenSSL的支持1.0.1,特别是TLSv1.1和TLSv1.2,默认情况下不启用这些协议.如果你没有做我做过的事情,你就无法利用TLSv1.2的支持,尽管在最新版本的Android上宣传了对TLSv1.2的支持.回顾以前的Android版本,细节会有很大差异.至少,您可能希望仔细查看所有受支持版本的默认值,并查看客户端实际执行的操作.你可能会感到惊讶.
关于对各种协议和密码的支持,你可以说更多.关键是,有时可能需要在客户端中更改这些设置.
A.使用自定义SSLSocketFactory
这对我来说效果很好,最后,代码并不多.但由于以下几个原因,它有点棘手:
关键点:
public class SecureSocketFactory extends SSLSocketFactory {
@Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
// order should not matter here; the server should select the highest
// one from this list that it supports
s.setEnabledProtocols(new String[] { "TLSv1.2", "TLSv1" });
// order matters here; specify in preference order …
Run Code Online (Sandbox Code Playgroud) 我有用于安全websocket连接的spring-boot Tomcat服务器.服务器接受Android 4.4,iOS,Firefox和Chrome客户端,并且没有使用授权签名证书的失败.但是,Android 5.0无法通过SSL握手.
Caused by: javax.net.ssl.SSLHandshakeException: Handshake failed
at com.android.org.conscrypt.OpenSSLEngineImpl.unwrap(OpenSSLEngineImpl.java:436)
at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:1006)
at org.glassfish.grizzly.ssl.SSLConnectionContext.unwrap(SSLConnectionContext.java:172)
at org.glassfish.grizzly.ssl.SSLUtils.handshakeUnwrap(SSLUtils.java:263)
at org.glassfish.grizzly.ssl.SSLBaseFilter.doHandshakeStep(SSLBaseFilter.java:603)
at org.glassfish.grizzly.ssl.SSLFilter.doHandshakeStep(SSLFilter.java:312)
at org.glassfish.grizzly.ssl.SSLBaseFilter.doHandshakeStep(SSLBaseFilter.java:552)
at org.glassfish.grizzly.ssl.SSLBaseFilter.handleRead(SSLBaseFilter.java:273)
at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:284)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:201)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:133)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:561)
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:565)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:545)
at java.lang.Thread.run(Thread.java:818)
Caused by: javax.net.ssl.SSLProtocolException: SSL handshake terminated: ssl=0xa1f34200: Failure in SSL library, usually a protocol error
error:1408E0F4:SSL routines:SSL3_GET_MESSAGE:unexpected message (external/openssl/ssl/s3_both.c:498 0xac526e61:0x00000000)
at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake_bio(Native Method)
at com.android.org.conscrypt.OpenSSLEngineImpl.unwrap(OpenSSLEngineImpl.java:423)
Run Code Online (Sandbox Code Playgroud)
我认为问题在于TLS或密码套件由于Android …