我有一个使用以下库的 android 应用程序(4.4.4+):
compile 'com.squareup.okhttp3:okhttp:3.2.0'
compile 'com.squareup.okhttp3:okhttp-urlconnection:3.2.0'
compile 'com.squareup.okio:okio:1.7.0'
我使用 OpenSSL 编译的 nginx(版本 1.9.14)(版本 1.0.2g 源代码编译)在 centOS 7 上使用 nginx -V 确认了 openSSL 的使用。为反向代理启用了 nginx http2 的配置:
server {
listen 443 ssl http2;
ssl on;
server_name mobile.site.com;
ssl_certificate /etc/pki/tls/certs/start_cert.pem;
ssl_certificate_key /etc/pki/tls/certs/start_cert.key;
proxy_cache one;
underscores_in_headers on;
access_log /var/log/nginx/ssl.log ssl_custom;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_cache_bypass $cookie_nocache $arg_nocache $arg_comment;
proxy_pass https://10.10.1.31:443;
}
}
在服务器上运行命令:
echo | openssl s_client -alpn h2 -connect
回报:
No client certificate CA names sent
Peer signing digest: SHA512
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 3718 bytes and written 442 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 4096 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
ALPN protocol: h2
从任何现代浏览器浏览 API URL 会导致在 SSL 日志和 HTTP/2 chrome 插件中显示 HTTP/2 连接。假设在 nginx/OpenSSL 中正确配置了 HTTP/2。
Android OKHttp 客户端拒绝 HTTP/2:
ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
.tlsVersions(TlsVersion.TLS_1_2)
.build();
okHttpClient = new OkHttpClient.Builder()
.followSslRedirects(true)
.protocols(Arrays.asList(Protocol.HTTP_2, Protocol.HTTP_1_1))
.connectionSpecs(Collections.singletonList(spec))
.sslSocketFactory(new TLSSocketFactory((SSLSocketFactory) TLSSocketFactory.getDefault()))
.retryOnConnectionFailure(true)
.connectTimeout(25, TimeUnit.SECONDS)
.connectionPool(new ConnectionPool(30, 120, TimeUnit.SECONDS))
.addInterceptor(new AddCookiesInterceptor())
.addInterceptor(new ReceivedCookiesInterceptor())
.build();
我编写了一个自定义 TLS 套接字工厂,以在 <= Android 4.4.4 上启用 TLS 1.2。
TLSv1.2 确实可以使用这个自定义套接字工厂在 4.4.4+ 上运行,但我也尝试在 5.0+ 上运行,无论是否使用自定义套接字工厂,都没有 HTTP/2 运气。
HTTP/2 在 kit-kat、棒棒糖和棉花糖上失败,但在“N”开发者预览版(又名纽约芝士蛋糕)上工作。不会抛出任何错误,只会以 HTTP/1.1 连接。我很难找到任何与 OKhttp 和 HTTP/2 相关的文章,大多数帮助问题/帖子只是说使用 ALPN,但没有资源来详细说明其用法。OkHTTP 文档并不清楚 HTTP/2 的使用和部署实践,但主页上说它支持它。任何帮助或专家指导将不胜感激,即使只是朝着正确的方向轻推也会是一个巨大的帮助。如果我错过了任何可能在此过程中提供帮助的内容,请告诉我,提前致谢!
更新 1:我发现了一个与此相关的 SO 问题,答案非常模糊:[SO 链接]如何在 Android 设备上将 http/2 与 Okhttp 一起使用?有一条评论建议使用码头,但仅限于桌面使用,而不是 Android 使用。
更新 2:本文显示 ALPN 已在 Android 4.4 中启用:https ://github.com/http2/http2-spec/wiki/ALPN-Status
更新 3:能够使用 +5.0 连接 HTTP/2,但不能使用 4.4.4。我不需要低于 4.4.4,因为内部目标设备是 http/2 的关注点,它们运行 4.4.4。我能够更新应用程序以使用 Google Play Services 安全协议作为 OKHttp 套接字连接,但我们使用的 4.4.4 设备未启用 Google,因此我无法在这些设备上使用 PlayServices 安全套接字。